pub fn normalize_path(path: &Path) -> Cow<'_, Path>Expand description
Normalize a path by removing . and .. components
This function provides a safe normalization that prevents path traversal attacks while not requiring the path to exist.
Warning: This function performs purely syntactic normalization. It does
NOT access the filesystem and therefore does not resolve symlinks.
A path like /a/b/../c will be normalized to /a/c even if /a/b is a
symlink pointing elsewhere. For security checks involving physical file
locations, use std::fs::canonicalize (or canonicalize_safe) instead.
Returns Cow::Borrowed when no normalization is needed (zero allocation),
or Cow::Owned when normalization is required.
§Security
- Removes all
.components - Collapses
..components safely - Prevents escaping the root directory on absolute paths
- Does not follow symlinks (syntactic only)
- Relative paths that collapse to empty always return
".", never""(prevents vacuousPath::starts_with("")→truein callers likeis_within_root)
§Performance
Fast-paths when the path is already normalized, avoiding allocation.
§Examples
use luff::fs_utils::normalize_path;
use std::path::Path;
let normalized = normalize_path(Path::new("./src/../README.md"));
assert_eq!(normalized.as_ref(), Path::new("README.md"));
// Already normalized paths return borrowed (no allocation)
let normalized = normalize_path(Path::new("src/main.rs"));
assert!(matches!(normalized, std::borrow::Cow::Borrowed(_)));
// Absolute paths cannot escape root
let normalized = normalize_path(Path::new("/../../etc/passwd"));
assert_eq!(normalized.as_ref(), Path::new("/etc/passwd"));
// "." and collapsing relative paths normalize to ".", not ""
let normalized = normalize_path(Path::new("."));
assert_eq!(normalized.as_ref(), Path::new("."));
let normalized = normalize_path(Path::new("foo/.."));
assert_eq!(normalized.as_ref(), Path::new("."));