From d4f62371f8abca7a77d12d64d720e640a96091b7 Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 3 Apr 2023 17:01:11 +0200 Subject: [PATCH] path normalization fixed for relative paths --- btrfs/src/path.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/btrfs/src/path.rs b/btrfs/src/path.rs index 39d582d..d437f91 100644 --- a/btrfs/src/path.rs +++ b/btrfs/src/path.rs @@ -38,8 +38,20 @@ pub trait Path: AsRef<[u8]> { Segment::NoOp | Segment::CurrentDir => {} Segment::Root | Segment::File(_) => segments.push_back(segment), Segment::ParentDir => { - if segments.back() != Some(&Segment::Root) { - segments.pop_back(); + match segments.back() { + // parent of root is still root, so do nothing + Some(&Segment::Root) => {} + // relative path has to contain parentdir going up past + // the current dir if segments already contain a + // parentdir we know we must be in a relative path above + // the current dir + None | Some(&Segment::ParentDir) => { + segments.push_back(segment); + } + // some path exists, pop up to parent + _ => { + segments.pop_back(); + } } } } @@ -168,6 +180,31 @@ mod tests { assert_eq!(iter.next(), Some(&b"some.file"[..])); assert_eq!(iter.next(), None); } + + #[test] + fn test_normalizing() { + // normalizes to "/path" + let path = b"///../../some/../path".normalize(); + let mut iter = path.into_iter(); + assert_eq!(iter.next(), Some(Segment::Root)); + assert_eq!(iter.next(), Some(Segment::File(&b"path"[..]))); + assert_eq!(iter.next(), None); + + // normalizes to "../../path" + let path = b"../../some/../path".normalize(); + let mut iter = path.into_iter(); + assert_eq!(iter.next(), Some(Segment::ParentDir)); + assert_eq!(iter.next(), Some(Segment::ParentDir)); + assert_eq!(iter.next(), Some(Segment::File(&b"path"[..]))); + assert_eq!(iter.next(), None); + + // normalizes to "../.." + let path = b".././../some/../path/..".normalize(); + let mut iter = path.into_iter(); + assert_eq!(iter.next(), Some(Segment::ParentDir)); + assert_eq!(iter.next(), Some(Segment::ParentDir)); + assert_eq!(iter.next(), None); + } } #[cfg(test)]