Skip to content

RelativeDirectoryPath.Normalize() drops leading "..": "../sibling" becomes "sibling", so the path points somewhere else #288

Description

@matt-edmondson

What's wrong

RelativeDirectoryPath.Normalize() (Semantics.Paths/Implementations/RelativeDirectoryPath.cs, around line 218) normalizes a relative path in three steps:

  1. Combine it with a dummy root (/ or C:\).
  2. Call Path.GetFullPath.
  3. Take GetRelativePath back from the dummy root.

A .. at the filesystem root resolves to the root itself, so every .. that climbs above the starting point is silently discarded.

Failure scenario (reproduced)

Input Normalize() returns Expected
"../sibling" "sibling" "../sibling"
"a/../../b" "b" "../b"
"../../x/y" "x/y" "../../x/y"

Take "../sibling" resolved from /home/user/project. Before normalizing it names /home/user/sibling. After normalizing it names /home/user/project/sibling. Normalization must never change which directory a path refers to. Here it can turn a path that points outside the base into one that points inside it, which affects file operations and makes any containment or sandbox check built on it unreliable.

The existing test Normalize_WithOnlyDots_ResolvesCorrectly (./../folder) only asserts that the result contains "folder", so it passes despite the bug.

Suggested fix

Resolve segments lexically with a stack:

  • skip .
  • a .. pops the previous segment when there is one that isn't itself ..
  • otherwise keep the ..

Then join with the platform separator. This needs no dummy base and gives the same result on every OS.

Acceptance criteria

  • The three inputs in the table above normalize to the expected column.
  • "a/./b/../c" → "a/c".
  • Normalize_WithOnlyDots_ResolvesCorrectly asserts the exact value ("../folder").

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    readyFully specified; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions