Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-core/src/utils/hg_path.rs @ 44312:c18dd48cea4a
rust-pathauditor: add Rust implementation of the `pathauditor`
It does not offer the same flexibility as the Python implementation, but
should check incoming paths just as well.
Differential Revision: https://phab.mercurial-scm.org/D7866
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Wed, 05 Feb 2020 17:05:37 +0100 |
parents | 732098027b34 |
children | 9ab4830e9e3d |
line wrap: on
line diff
--- a/rust/hg-core/src/utils/hg_path.rs Wed Jan 22 03:17:06 2020 +0530 +++ b/rust/hg-core/src/utils/hg_path.rs Wed Feb 05 17:05:37 2020 +0100 @@ -15,12 +15,35 @@ pub enum HgPathError { /// Bytes from the invalid `HgPath` LeadingSlash(Vec<u8>), - /// Bytes and index of the second slash - ConsecutiveSlashes(Vec<u8>, usize), - /// Bytes and index of the null byte - ContainsNullByte(Vec<u8>, usize), + ConsecutiveSlashes { + bytes: Vec<u8>, + second_slash_index: usize, + }, + ContainsNullByte { + bytes: Vec<u8>, + null_byte_index: usize, + }, /// Bytes DecodeError(Vec<u8>), + /// The rest come from audit errors + EndsWithSlash(HgPathBuf), + ContainsIllegalComponent(HgPathBuf), + /// Path is inside the `.hg` folder + InsideDotHg(HgPathBuf), + IsInsideNestedRepo { + path: HgPathBuf, + nested_repo: HgPathBuf, + }, + TraversesSymbolicLink { + path: HgPathBuf, + symlink: HgPathBuf, + }, + NotFsCompliant(HgPathBuf), + /// `path` is the smallest invalid path + NotUnderRoot { + path: PathBuf, + root: PathBuf, + }, } impl ToString for HgPathError { @@ -29,17 +52,55 @@ HgPathError::LeadingSlash(bytes) => { format!("Invalid HgPath '{:?}': has a leading slash.", bytes) } - HgPathError::ConsecutiveSlashes(bytes, pos) => format!( - "Invalid HgPath '{:?}': consecutive slahes at pos {}.", + HgPathError::ConsecutiveSlashes { + bytes, + second_slash_index: pos, + } => format!( + "Invalid HgPath '{:?}': consecutive slashes at pos {}.", bytes, pos ), - HgPathError::ContainsNullByte(bytes, pos) => format!( + HgPathError::ContainsNullByte { + bytes, + null_byte_index: pos, + } => format!( "Invalid HgPath '{:?}': contains null byte at pos {}.", bytes, pos ), HgPathError::DecodeError(bytes) => { format!("Invalid HgPath '{:?}': could not be decoded.", bytes) } + HgPathError::EndsWithSlash(path) => { + format!("Audit failed for '{}': ends with a slash.", path) + } + HgPathError::ContainsIllegalComponent(path) => format!( + "Audit failed for '{}': contains an illegal component.", + path + ), + HgPathError::InsideDotHg(path) => format!( + "Audit failed for '{}': is inside the '.hg' folder.", + path + ), + HgPathError::IsInsideNestedRepo { + path, + nested_repo: nested, + } => format!( + "Audit failed for '{}': is inside a nested repository '{}'.", + path, nested + ), + HgPathError::TraversesSymbolicLink { path, symlink } => format!( + "Audit failed for '{}': traverses symbolic link '{}'.", + path, symlink + ), + HgPathError::NotFsCompliant(path) => format!( + "Audit failed for '{}': cannot be turned into a \ + filesystem path.", + path + ), + HgPathError::NotUnderRoot { path, root } => format!( + "Audit failed for '{}': not under root {}.", + path.display(), + root.display() + ), } } } @@ -229,17 +290,17 @@ for (index, byte) in bytes.iter().enumerate() { match byte { 0 => { - return Err(HgPathError::ContainsNullByte( - bytes.to_vec(), - index, - )) + return Err(HgPathError::ContainsNullByte { + bytes: bytes.to_vec(), + null_byte_index: index, + }) } b'/' => { if previous_byte.is_some() && previous_byte == Some(b'/') { - return Err(HgPathError::ConsecutiveSlashes( - bytes.to_vec(), - index, - )); + return Err(HgPathError::ConsecutiveSlashes { + bytes: bytes.to_vec(), + second_slash_index: index, + }); } } _ => (), @@ -431,11 +492,17 @@ HgPath::new(b"/").check_state() ); assert_eq!( - Err(HgPathError::ConsecutiveSlashes(b"a/b//c".to_vec(), 4)), + Err(HgPathError::ConsecutiveSlashes { + bytes: b"a/b//c".to_vec(), + second_slash_index: 4 + }), HgPath::new(b"a/b//c").check_state() ); assert_eq!( - Err(HgPathError::ContainsNullByte(b"a/b/\0c".to_vec(), 4)), + Err(HgPathError::ContainsNullByte { + bytes: b"a/b/\0c".to_vec(), + null_byte_index: 4 + }), HgPath::new(b"a/b/\0c").check_state() ); // TODO test HgPathError::DecodeError for the Windows implementation.