From dddba110843a2ad294ab0e6cbf97cebadb367366 Mon Sep 17 00:00:00 2001 From: hamdiakin Date: Mon, 21 Sep 2026 21:24:27 +0300 Subject: [PATCH 1/3] PathStrings: guard drive-letter normalization by platform --- TruePath.Tests/PathStringsTests.cs | 29 +++++++++++++++++++++++++++++ TruePath/PathStrings.cs | 7 +++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/TruePath.Tests/PathStringsTests.cs b/TruePath.Tests/PathStringsTests.cs index 5ed8d84..0dccc26 100644 --- a/TruePath.Tests/PathStringsTests.cs +++ b/TruePath.Tests/PathStringsTests.cs @@ -128,6 +128,35 @@ public void WindowsSpecificDotFoldersAreTraversed(string input, string expected) } } + [Theory] + [InlineData("C:/", "C:")] + [InlineData("C:/../file", "file")] + public void Normalize_DriveLetterCheckDisabled_TreatsColonAsRegularPathCharacter(string input, string expected) + { + var actual = PathStrings.Normalize(input, checkDriveLetter: false); + + Assert.Equal(NormalizeSeparators(expected), actual); + } + + [Theory] + [InlineData("C:/", "C:/")] + [InlineData("C:/../file", "C:/../file")] + public void Normalize_DriveLetterCheckEnabled_PreservesWindowsDrivePrefix(string input, string expected) + { + var actual = PathStrings.Normalize(input, checkDriveLetter: true); + + Assert.Equal(NormalizeSeparators(expected), actual); + } + + [Fact] + public void Normalize_DriveLetterHandling_MatchesCurrentPlatform() + { + var actual = PathStrings.Normalize("C:/../file"); + var expected = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "C:/../file" : "file"; + + Assert.Equal(NormalizeSeparators(expected), actual); + } + private static string NormalizeSeparators(string path) => path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); } diff --git a/TruePath/PathStrings.cs b/TruePath/PathStrings.cs index 1054176..925bbc7 100644 --- a/TruePath/PathStrings.cs +++ b/TruePath/PathStrings.cs @@ -46,12 +46,15 @@ public static class PathStrings /// Note that this operation will never perform any file IO, and is purely string manipulation. /// /// + public static string Normalize(string path) => + Normalize(path, checkDriveLetter: Path.DirectorySeparatorChar == '\\'); + #if NET8_0_OR_GREATER [SkipLocalsInit] // is necessary to prevent the CLR from filling stackalloc with zeros. #endif - public static string Normalize(string path) + internal static string Normalize(string path, bool checkDriveLetter) { - bool containsDriveLetter = SourceContainsDriveLetter(path.AsSpan()); + bool containsDriveLetter = checkDriveLetter && SourceContainsDriveLetter(path.AsSpan()); int written = 0; From e45f4694bc28c018408dab3d3f5a1980d4332762 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Tue, 22 Sep 2026 22:09:40 +0200 Subject: [PATCH 2/3] PathStrings: minor clarification and cleanup --- TruePath.Tests/PathStringsTests.cs | 4 ++-- TruePath/PathStrings.cs | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/TruePath.Tests/PathStringsTests.cs b/TruePath.Tests/PathStringsTests.cs index 0dccc26..d2cb083 100644 --- a/TruePath.Tests/PathStringsTests.cs +++ b/TruePath.Tests/PathStringsTests.cs @@ -133,7 +133,7 @@ public void WindowsSpecificDotFoldersAreTraversed(string input, string expected) [InlineData("C:/../file", "file")] public void Normalize_DriveLetterCheckDisabled_TreatsColonAsRegularPathCharacter(string input, string expected) { - var actual = PathStrings.Normalize(input, checkDriveLetter: false); + var actual = PathStrings.Normalize(input, driveBasedSystem: false); Assert.Equal(NormalizeSeparators(expected), actual); } @@ -143,7 +143,7 @@ public void Normalize_DriveLetterCheckDisabled_TreatsColonAsRegularPathCharacter [InlineData("C:/../file", "C:/../file")] public void Normalize_DriveLetterCheckEnabled_PreservesWindowsDrivePrefix(string input, string expected) { - var actual = PathStrings.Normalize(input, checkDriveLetter: true); + var actual = PathStrings.Normalize(input, driveBasedSystem: true); Assert.Equal(NormalizeSeparators(expected), actual); } diff --git a/TruePath/PathStrings.cs b/TruePath/PathStrings.cs index 925bbc7..f65ce1a 100644 --- a/TruePath/PathStrings.cs +++ b/TruePath/PathStrings.cs @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2024 TruePath contributors +// SPDX-FileCopyrightText: 2024-2026 TruePath contributors // // SPDX-License-Identifier: MIT using System.Buffers; +using System.Runtime.InteropServices; +#if NET8_0_OR_GREATER using System.Runtime.CompilerServices; +#endif namespace TruePath; @@ -47,14 +50,14 @@ public static class PathStrings /// /// public static string Normalize(string path) => - Normalize(path, checkDriveLetter: Path.DirectorySeparatorChar == '\\'); + Normalize(path, driveBasedSystem: RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); #if NET8_0_OR_GREATER [SkipLocalsInit] // is necessary to prevent the CLR from filling stackalloc with zeros. #endif - internal static string Normalize(string path, bool checkDriveLetter) + internal static string Normalize(string path, bool driveBasedSystem) { - bool containsDriveLetter = checkDriveLetter && SourceContainsDriveLetter(path.AsSpan()); + bool containsDriveLetter = driveBasedSystem && SourceContainsDriveLetter(path.AsSpan()); int written = 0; From 52fbaf7ef0071b39f2b4507e1737ffcc7619c991 Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Tue, 22 Sep 2026 22:24:28 +0200 Subject: [PATCH 3/3] LocalPath: fix the doc warning --- TruePath/LocalPath.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TruePath/LocalPath.cs b/TruePath/LocalPath.cs index 350b0a1..bdc8578 100644 --- a/TruePath/LocalPath.cs +++ b/TruePath/LocalPath.cs @@ -15,8 +15,8 @@ namespace TruePath; /// (e.g. the parent of foo). /// /// -/// Always stored in a normalized form. Read the documentation on to -/// know what form of normalization the path uses. +/// Always stored in a normalized form. Read the documentation on +/// to know what form of normalization the path uses. /// /// public readonly struct LocalPath(string value) : IEquatable, IComparable, IPath, IPath