Browse Source

fix(identity): compare an identity with a name without the culture of the thread

IdentityReference2.Equals(string) lowercased both names with ToLower(), which uses the
culture of the thread. In tr-TR, I becomes U+0131, so an account whose name holds an
uppercase I (NT AUTHORITY\SYSTEM, BUILTIN\Administrators) no longer matched the same name in
another case, for example $entry.Account -eq 'nt authority\system'. Compare with
StringComparison.OrdinalIgnoreCase.

The test sets the culture of the thread to tr-TR and compares the system account with its name
in three cases. Before the fix it fails in all four configurations (elevated and basic user,
Windows PowerShell 5.1 and PowerShell 7); after it, all rows pass. The unit suite under tr-TR
did not find it, because no test compares a name that holds an uppercase I.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
ai/coverage-unknowns
Raimund Andree 1 day ago
parent
commit
419cfb3f6c
  1. 6
      CHANGELOG.md
  2. 3
      Security2/IdentityReference2.cs
  3. 19
      Tests/ObjectApis.Tests.ps1

6
CHANGELOG.md

@ -439,5 +439,11 @@ The format is based on
- Fix [Get-ChildItem2](Docs/Cmdlets/Get-ChildItem2.md) with `-Hidden`,
which omitted the first hidden item unless `-Force` was also supplied
- Fix the comparison of an identity with a name, such as
`$entry.Account -eq 'nt authority\system'`, in the Turkish culture
(`tr-TR`): it changed the case of both names with the culture of the thread,
which turns `I` into a dotless `ı`, so an account whose name holds an
uppercase `I`, such as `NT AUTHORITY\SYSTEM` or `BUILTIN\Administrators`,
did not match the same name in another case
[Unreleased]: https://github.com/raandree/NTFSSecurity/compare/4.2.6...HEAD

3
Security2/IdentityReference2.cs

@ -195,7 +195,8 @@ namespace Security2
if (this.ntAccount != null)
{
if (this.ntAccount.Value.ToLower() == value.ToLower())
// Not ToLower: with the culture of the thread, tr-TR lowercases I to U+0131 and misses names such as NT AUTHORITY\SYSTEM.
if (string.Equals(this.ntAccount.Value, value, StringComparison.OrdinalIgnoreCase))
{
return true;
}

19
Tests/ObjectApis.Tests.ps1

@ -159,6 +159,25 @@ Describe 'Identity comparisons and conversions' {
$identity.Equals($other) | Should -Be $Expected
}
# tr-TR lowercases I to U+0131, so a comparison that lowercases both names with the current culture misses an account name that holds an
# uppercase I (NT AUTHORITY, BUILTIN) when the other name has another case. The name must match in every culture.
It 'Should compare a name with the account ignoring case in Turkish, where I and i are different letters' {
$system = [Security2.IdentityReference2] 'S-1-5-18'
$system.AccountName | Should -MatchExactly 'I' -Because 'the test needs an account name with an uppercase I'
$original = [System.Threading.Thread]::CurrentThread.CurrentCulture
try {
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('tr-TR')
'I'.ToLower() | Should -Be ([string][char]0x131) -Because 'the culture of the thread has to be Turkish for the test to mean anything'
$system.Equals($system.AccountName) | Should -BeTrue
$system.Equals($system.AccountName.ToLowerInvariant()) | Should -BeTrue
$system.Equals($system.AccountName.ToUpperInvariant()) | Should -BeTrue
$system.Equals('NTFSSecurity-not-an-account') | Should -BeFalse
}
finally {
[System.Threading.Thread]::CurrentThread.CurrentCulture = $original
}
}
It 'Should compare null operands and distinct instances through both operators' {
$same = [Security2.IdentityReference2] 'S-1-1-0'
$different = [Security2.IdentityReference2] 'S-1-5-32-546'

Loading…
Cancel
Save