@@ -336,31 +336,9 @@ try {
336336 if ([Convert]::ToBase64String($control) -cne 'dGlueXNlY3VyaXR5LXJlYWQtY29udHJvbC12MQ==') { exit 85 }
337337} catch { exit 85 }
338338Write-Output 'audit-account-stage=91 exact-control-read=1'
339- $auditFileOrdinal = 0
340- $auditOperation = 0
341- $auditCallsite = 0
342- try {
343- foreach ($name in @('audit', 'audit.1', 'audit.2', 'audit.3', 'audit.lock', 'audit.journal')) {
344- $auditFileOrdinal++
345- $auditOperation = 1
346- $auditCallsite = 1
347- try { [void][IO.File]::ReadAllBytes((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name)); exit 83 }
348- catch [UnauthorizedAccessException] { }
349- $auditOperation = 2
350- $auditCallsite = 2
351- try { [IO.File]::WriteAllBytes((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name), [byte[]]@(0)); exit 87 }
352- catch [UnauthorizedAccessException] { }
353- $auditOperation = 3
354- $auditCallsite = 3
355- # Framework File.Move checks InternalExists first, masking denied metadata
356- # as FileNotFound. FileInfo.MoveTo reaches native MoveFile without that check.
357- try { [IO.FileInfo]::new((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name)).MoveTo((Join-Path $env:TINYSECURITY_TEST_DIRECTORY ($name + '.outsider'))); exit 88 }
358- catch [UnauthorizedAccessException] { }
359- }
360- } catch {
339+ function Write-AuditFailureMetadata($failure, $auditFileOrdinal, $auditOperation, $auditCallsite) {
361340 # Unexpected errors still fail. Emit only fixed file/operation ordinals and
362341 # numeric exception metadata; never stringify paths, records or messages.
363- $failure = $_
364342 [Console]::WriteLine(('audit-account-stage=99 file={0} operation={1} callsite={2} line={3} offset={4} category={5}' -f $auditFileOrdinal,$auditOperation,$auditCallsite,$failure.InvocationInfo.ScriptLineNumber,$failure.InvocationInfo.OffsetInLine,[int]$failure.CategoryInfo.Category))
365343 $exception = $failure.Exception
366344 for ($depth = 0; ($null -ne $exception) -and ($depth -lt 8); $depth++) {
@@ -382,11 +360,43 @@ try {
382360 [Console]::WriteLine(('audit-account-stage=99 depth={0} kind={1} hresult={2} lowword={3} native={4}' -f $depth,$kind,$exception.HResult,($exception.HResult -band 65535),$native))
383361 $exception = $exception.InnerException
384362 }
363+ }
364+ $auditFileOrdinal = 0
365+ $auditOperation = 0
366+ $auditCallsite = 0
367+ try {
368+ foreach ($name in @('audit', 'audit.1', 'audit.2', 'audit.3', 'audit.lock', 'audit.journal')) {
369+ $auditFileOrdinal++
370+ $auditOperation = 1
371+ $auditCallsite = 1
372+ try { [void][IO.File]::ReadAllBytes((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name)); exit 83 }
373+ catch [UnauthorizedAccessException] { }
374+ $auditOperation = 2
375+ $auditCallsite = 2
376+ try { [IO.File]::WriteAllBytes((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name), [byte[]]@(0)); exit 87 }
377+ catch [UnauthorizedAccessException] { }
378+ $auditOperation = 3
379+ $auditCallsite = 3
380+ # Framework File.Move checks InternalExists first, masking denied metadata
381+ # as FileNotFound. FileInfo.MoveTo reaches native MoveFile without that check.
382+ try { [IO.FileInfo]::new((Join-Path $env:TINYSECURITY_TEST_DIRECTORY $name)).MoveTo((Join-Path $env:TINYSECURITY_TEST_DIRECTORY ($name + '.outsider'))); exit 88 }
383+ catch [UnauthorizedAccessException] { }
384+ }
385+ } catch {
386+ Write-AuditFailureMetadata $_ $auditFileOrdinal $auditOperation $auditCallsite
385387 throw
386388}
387389Write-Output 'audit-account-stage=92 private-file-denials=6'
388- try { [IO.Directory]::Move($env:TINYSECURITY_TEST_DIRECTORY, ($env:TINYSECURITY_TEST_DIRECTORY + '.outsider')); exit 84 }
389- catch [UnauthorizedAccessException] { }
390+ $auditFileOrdinal = 7
391+ $auditOperation = 3
392+ $auditCallsite = 4
393+ try {
394+ try { [IO.Directory]::Move($env:TINYSECURITY_TEST_DIRECTORY, ($env:TINYSECURITY_TEST_DIRECTORY + '.outsider')); exit 84 }
395+ catch [UnauthorizedAccessException] { }
396+ } catch {
397+ Write-AuditFailureMetadata $_ $auditFileOrdinal $auditOperation $auditCallsite
398+ throw
399+ }
390400Write-Output 'audit-account-stage=93 namespace-denial=1'
391401exit 0
392402'@
@@ -437,7 +447,7 @@ exit 0
437447 $requiredPhases = @('audit-account-stage=90 foreign-identity=1 nonadmin=1', 'audit-account-stage=91 exact-control-read=1', 'audit-account-stage=92 private-file-denials=6', 'audit-account-stage=93 namespace-denial=1')
438448 $allLines = @($stdout.Result.Split([char]10) | ForEach-Object { $_.TrimEnd([char]13) } | Where-Object { $_.Length -gt 0 })
439449 $lines = @($allLines | Where-Object { $requiredPhases -ccontains $_ })
440- $diagnostics = @($allLines | Where-Object { $_ -cmatch '^audit-account-stage=94 parsed=1 source-first=[0-9]+ ordinal-prefix=[01] ordinal-first=[01]$|^audit-account-stage=95 preference-extra=[0-2] codepoint=[0-9]+ length=[0-9]+ category=[0-9]+ hresult=-?[0-9]+$|^audit-account-stage=96 (child-entry|identity-read)=1$|^audit-account-stage=98 child-foreign-present=[01] child-foreign-nonempty=[01] child-owner-present=[01] child-owner-nonempty=[01] child-directory-present=[01] child-directory-nonempty=[01] identity-foreign-match=[01] identity-owner-match=[01]$|^audit-account-stage=99 file=[0-6 ] operation=[0-3] callsite=[0-3 ] line=[0-9]+ offset=[0-9]+ category=[0-9]+$|^audit-account-stage=99 depth=[0-7] kind=(10|[0-9]) hresult=-?[0-9]+ lowword=[0-9]+ native=-?[0-9]+$' })
450+ $diagnostics = @($allLines | Where-Object { $_ -cmatch '^audit-account-stage=94 parsed=1 source-first=[0-9]+ ordinal-prefix=[01] ordinal-first=[01]$|^audit-account-stage=95 preference-extra=[0-2] codepoint=[0-9]+ length=[0-9]+ category=[0-9]+ hresult=-?[0-9]+$|^audit-account-stage=96 (child-entry|identity-read)=1$|^audit-account-stage=98 child-foreign-present=[01] child-foreign-nonempty=[01] child-owner-present=[01] child-owner-nonempty=[01] child-directory-present=[01] child-directory-nonempty=[01] identity-foreign-match=[01] identity-owner-match=[01]$|^audit-account-stage=99 file=[0-7 ] operation=[0-3] callsite=[0-4 ] line=[0-9]+ offset=[0-9]+ category=[0-9]+$|^audit-account-stage=99 depth=[0-7] kind=(10|[0-9]) hresult=-?[0-9]+ lowword=[0-9]+ native=-?[0-9]+$' })
441451 foreach ($line in $allLines) {
442452 if (($requiredPhases -ccontains $line) -or ($diagnostics -ccontains $line)) { Write-Output $line }
443453 }
0 commit comments