use crate::error::PathError;
use crate::internal::components::starts_with_components;
use crate::internal::validation::reject_nul_path;
use crate::normalize::normalize;
use std::path::{Path, PathBuf};
pub fn is_lexically_inside(path: &Path, root: &Path) -> bool {
if path == root {
return true;
}
starts_with_components(path, root)
}
pub fn ensure_inside(root: impl AsRef<Path>, path: impl AsRef<Path>) -> Result<PathBuf, PathError> {
let root = normalize(root.as_ref())?;
let path = normalize(path.as_ref())?;
reject_nul_path(&root)?;
reject_nul_path(&path)?;
if is_lexically_inside(&path, &root) {
Ok(path)
} else {
Err(PathError::root_escape(path))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn inside_and_escape() {
let root = Path::new("/repo");
assert!(is_lexically_inside(Path::new("/repo/src"), root));
assert!(is_lexically_inside(Path::new("/repo"), root));
assert!(!is_lexically_inside(Path::new("/etc"), root));
assert!(!is_lexically_inside(Path::new("/repo2"), root));
}
}