Skip to content

AbsolutePath.GetCanonicalForm() silently accepts invalid path characters that Path.GetFullPath would reject #13514

Description

@OvesN

When migrating SGen task from Path.GetFullPath(path) to TaskEnvironment.GetAbsolutePath(path).GetCanonicalForm().Value,
there is a behavioral difference in how invalid path characters are handled.

Path.GetFullPath behavior:

  • Throws ArgumentException for paths containing invalid characters
  • Task relied on this exception to detect and report invalid paths via Log.LogErrorWithCodeFromResources

TaskEnvironment.GetAbsolutePath(path).GetCanonicalForm().Value behavior:

  1. GetAbsolutePath → new AbsolutePath(path, basePath) → calls Path.Combine(basePath, path) which intentionally does
    not throw for invalid characters (see comment in AbsolutePath.cs line 109: "This function should not throw when
    path has illegal characters")
  2. GetCanonicalForm() → checks if the path has relative segments (/., .), separator normalization needs, or
    consecutive separators. If none of these are detected, it short-circuits and returns the path as-is without calling
    Path.GetFullPath
  3. Path.GetFullPath (which would throw on invalid characters) is never reached

Impact: Tasks that previously caught IO-related exceptions from Path.GetFullPath to log user-friendly errors now
silently accept invalid paths. The invalid path propagates further into the build pipeline and may cause confusing
failures elsewhere.

Possible fixes:

  1. Add invalid character validation in the AbsolutePath constructor or GetCanonicalForm(). We should also check
    whether GetCanonicalForm() behaves the same as Path.GetFullPath for other inputs that could potentially throw
    exceptions.
  2. Determine whether the optimization in GetCanonicalForm() that skips calling Path.GetFullPath in certain cases
    provides a significant performance benefit. If not, we can simplify by always calling Path.GetFullPath.

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions