Skip to main content

normalize_path

Function normalize_path 

Source
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 vacuous Path::starts_with("")true in callers like is_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("."));