fix(installer): payload verification broke on 8.3 short paths
A Server 2019 install reported all 96 payload files as simultaneously missing and unexpected, with mangled names - wheels/heels/flask.whl, python/ython/python-3.14.6-amd64.exe, mysqlclient/lient/mysql.exe. Exactly five characters of each directory name survived, which is the difference between ADMINI~1 and Administrator. Inno extracts the bundle under C:\Users\ADMINI~1\AppData\Local\Temp\..., an 8.3 SHORT path. Resolve-Path kept that short form while Get-ChildItem returned the long one, so the root was five characters shorter than the prefix being sliced off every FullName, and every relative key came out wrong. The payload was correct; the comparison was not - the verifier refused a perfectly good bundle. The root now comes from Get-Item, which goes through the same provider as Get-ChildItem so their path forms agree, and the prefix is checked with StartsWith before being trimmed. If the two ever disagree again this throws instead of inventing paths. Verified against the real failure mode rather than assumed: running the check through C:\SHOPDB~3\bundle in a Windows VM now passes. Nothing on Linux or in a normally-pathed Windows directory could have caught this - the short name only appears under a profile directory long enough to need one, which is where Setup extracts.
This commit is contained in:
@@ -76,14 +76,35 @@ function Get-FileDigest {
|
||||
}
|
||||
|
||||
function Get-PayloadFiles {
|
||||
# Every file in the directory, keyed by its path RELATIVE to that directory
|
||||
# with forward slashes, so a lock generated on Windows reads the same from
|
||||
# the Bash builder.
|
||||
<#
|
||||
Every file in the directory, keyed by its path RELATIVE to that directory
|
||||
with forward slashes, so a lock generated on Windows reads the same from
|
||||
the Bash builder.
|
||||
|
||||
The root comes from Get-Item, NOT Resolve-Path, and the prefix is checked
|
||||
before it is trimmed. Both matter, and a real install proved it:
|
||||
|
||||
Inno extracts the bundle under C:\Users\ADMINI~1\AppData\Local\Temp\... -
|
||||
an 8.3 SHORT path. Resolve-Path kept that short form while Get-ChildItem
|
||||
returned the long one (Administrator), so the root was five characters
|
||||
shorter than the prefix it was slicing off. Every relative path came out
|
||||
mangled - 'wheels/heels/flask.whl' - and the verifier reported all 96 files
|
||||
as simultaneously missing and unexpected. The payload was fine; the
|
||||
comparison was not.
|
||||
|
||||
Get-Item and Get-ChildItem go through the same provider, so their path
|
||||
forms agree. The StartsWith guard means that if they ever disagree again
|
||||
this fails loudly instead of inventing paths.
|
||||
#>
|
||||
param([string] $Dir)
|
||||
$out = @{}
|
||||
if (-not (Test-Path $Dir)) { return $out }
|
||||
$root = (Resolve-Path $Dir).Path.TrimEnd('\', '/')
|
||||
foreach ($f in (Get-ChildItem $Dir -Recurse -File)) {
|
||||
$rootItem = Get-Item -LiteralPath $Dir
|
||||
$root = $rootItem.FullName.TrimEnd('\', '/')
|
||||
foreach ($f in (Get-ChildItem -LiteralPath $rootItem.FullName -Recurse -File)) {
|
||||
if (-not $f.FullName.StartsWith($root, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw ("cannot place '{0}' beneath '{1}' - path forms disagree (8.3 short name?)" -f $f.FullName, $root)
|
||||
}
|
||||
$rel = $f.FullName.Substring($root.Length).TrimStart('\', '/').Replace('\', '/')
|
||||
$out[$rel] = @{ sha256 = (Get-FileDigest $f.FullName); size = $f.Length }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user