aboutsummaryrefslogtreecommitdiff
path: root/crates/fparkan-path/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/fparkan-path/src')
-rw-r--r--crates/fparkan-path/src/lib.rs27
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");