diff options
Diffstat (limited to 'crates/fparkan-path/src')
| -rw-r--r-- | crates/fparkan-path/src/lib.rs | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/crates/fparkan-path/src/lib.rs b/crates/fparkan-path/src/lib.rs index d15aae8..f59fda0 100644 --- a/crates/fparkan-path/src/lib.rs +++ b/crates/fparkan-path/src/lib.rs @@ -110,7 +110,7 @@ impl std::error::Error for PathError {} /// Returns [`PathError`] when the input is empty, absolute, contains an /// embedded NUL, attempts parent traversal, or is not valid UTF-8 after /// legacy separator normalization. -pub fn normalize_relative(raw: &[u8], _policy: PathPolicy) -> Result<NormalizedPath, PathError> { +pub fn normalize_relative(raw: &[u8], policy: PathPolicy) -> Result<NormalizedPath, PathError> { if raw.is_empty() { return Err(PathError::Empty); } @@ -124,11 +124,17 @@ pub fn normalize_relative(raw: &[u8], _policy: PathPolicy) -> Result<NormalizedP let mut parts = Vec::new(); for part in text.split(['/', '\\']) { if part.is_empty() || part == "." { + if policy == PathPolicy::StrictLegacy { + return Err(PathError::ParentTraversal); + } continue; } if part == ".." { return Err(PathError::ParentTraversal); } + if policy == PathPolicy::StrictLegacy && part.contains(':') { + return Err(PathError::Absolute); + } parts.push(part); } if parts.is_empty() { @@ -224,6 +230,25 @@ mod tests { } #[test] + fn strict_legacy_rejects_host_only_segments() { + assert_eq!( + normalize_relative(b"./DATA/MAPS", PathPolicy::StrictLegacy), + Err(PathError::ParentTraversal) + ); + assert_eq!( + normalize_relative(b"DATA//MAPS", PathPolicy::StrictLegacy), + Err(PathError::ParentTraversal) + ); + assert_eq!( + normalize_relative(b"DATA/stream:name", PathPolicy::StrictLegacy), + Err(PathError::Absolute) + ); + + let host = normalize_relative(b"./DATA//MAPS", PathPolicy::HostCompatible).expect("host"); + assert_eq!(host.as_str(), "DATA/MAPS"); + } + + #[test] fn join_under_keeps_normalized_path_below_root() { let rel = normalize_relative(b"DATA/MAPS/Land.map", PathPolicy::StrictLegacy) .expect("relative path"); |
