Skip to content

Commit 3405467

Browse files
Preserve malformed JSON array shape and literal artifact filenames
1 parent 20578d1 commit 3405467

6 files changed

Lines changed: 46 additions & 10 deletions

File tree

‎.github/actions/Publish-PSModule/src/publish.ps1‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ LogGroup 'Load inputs' {
6565
#region Load release context
6666
LogGroup 'Load release context' {
6767
$pullRequestJson = $env:PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest
68-
$pullRequest = if (-not [string]::IsNullOrWhiteSpace($pullRequestJson) -and $pullRequestJson -ne 'null') {
69-
$pullRequestJson | ConvertFrom-Json
68+
$pullRequest = $null
69+
if (-not [string]::IsNullOrWhiteSpace($pullRequestJson) -and $pullRequestJson -ne 'null') {
70+
$pullRequest = ConvertFrom-Json -InputObject $pullRequestJson -NoEnumerate -ErrorAction Stop
7071
} else {
7172
$githubEventJson = Get-Content -Raw $env:GITHUB_EVENT_PATH
7273
$githubEvent = $githubEventJson | ConvertFrom-Json
7374
if ($githubEvent.pull_request) {
74-
[pscustomobject]@{
75+
$pullRequest = [pscustomobject]@{
7576
Number = $githubEvent.pull_request.number
7677
}
7778
}

‎.github/actions/Publish-PSModule/tests/Publish-PSModule.Preflight.Tests.ps1‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,10 @@ Describe 'Publish-PSModule source-bound preflight' {
365365
@{ Json = '{"Number":0}' }
366366
@{ Json = '{"Number":"unknown"}' }
367367
@{ Json = '42' }
368+
@{ Json = '[]' }
369+
@{ Json = '[null]' }
370+
@{ Json = '[{"Number":42}]' }
371+
@{ Json = '[{"Number":0}]' }
368372
) {
369373
$env:PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest = $Json
370374

‎.github/actions/Release-PSModule/src/Release-PSModule.Helpers.psm1‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ function Get-PSModuleProducingPullRequestNumber {
153153
return 0L
154154
}
155155
$number = 0L
156-
if (($PullRequest -isnot [PSCustomObject] -and $PullRequest -isnot [Collections.IDictionary]) -or
156+
if ($PullRequest -is [array] -or
157+
($PullRequest -isnot [PSCustomObject] -and $PullRequest -isnot [Collections.IDictionary]) -or
157158
-not [long]::TryParse([string]$PullRequest.Number, [ref]$number) -or $number -lt 1) {
158159
throw 'Supplied pull request context requires a positive producing pull request number.'
159160
}
@@ -341,8 +342,13 @@ function Get-PSModuleArtifactFile {
341342
throw 'The tested module artifact contains no files.'
342343
}
343344
foreach ($file in $files) {
345+
$relativePath = [IO.Path]::GetRelativePath($root, $file.FullName)
346+
$relativePath = $relativePath.Replace([IO.Path]::DirectorySeparatorChar, [char]'/')
347+
if ($relativePath.Contains('\')) {
348+
throw 'The tested artifact contains a literal filename backslash. Refusing to rename its published file tree.'
349+
}
344350
[pscustomobject]@{
345-
RelativePath = [IO.Path]::GetRelativePath($root, $file.FullName).Replace('\', '/')
351+
RelativePath = $relativePath
346352
FullName = $file.FullName
347353
}
348354
}

‎.github/actions/Release-PSModule/src/release.ps1‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ LogGroup 'Load release context' {
9999
$githubEventJson = Get-Content -Raw $env:GITHUB_EVENT_PATH
100100
$githubEvent = $githubEventJson | ConvertFrom-Json
101101
$pullRequestJson = $env:PSMODULE_RELEASE_PSMODULE_INPUT_PullRequest
102-
$pullRequest = if (-not [string]::IsNullOrWhiteSpace($pullRequestJson) -and $pullRequestJson -ne 'null') {
103-
$pullRequestJson | ConvertFrom-Json
102+
$pullRequest = $null
103+
if (-not [string]::IsNullOrWhiteSpace($pullRequestJson) -and $pullRequestJson -ne 'null') {
104+
$pullRequest = ConvertFrom-Json -InputObject $pullRequestJson -NoEnumerate -ErrorAction Stop
104105
} elseif ($githubEvent.pull_request) {
105-
[pscustomobject]@{
106+
$pullRequest = [pscustomobject]@{
106107
Number = $githubEvent.pull_request.number
107108
Title = $githubEvent.pull_request.title
108109
Body = $githubEvent.pull_request.body

‎.github/actions/Release-PSModule/tests/Release-PSModule.Ownership.Tests.ps1‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,25 @@ Describe 'Tested artifact identity' {
137137
Get-PSModuleArtifactDigest -Path $script:modulePath | Should -Not -BeExactly $original
138138
}
139139

140+
It 'rejects a literal Unix filename backslash before hashing or creating an archive' -Skip:$IsWindows {
141+
[IO.File]::WriteAllText([IO.Path]::Combine($script:modulePath, 'data\value.txt'), 'Literal filename bytes.')
142+
$archivePath = Join-Path -Path $TestDrive -ChildPath 'rejected-backslash.zip'
143+
144+
{ Get-PSModuleArtifactDigest -Path $script:modulePath } | Should -Throw '*backslash*'
145+
{ New-PSModuleReleaseArchive -Path $script:modulePath -DestinationPath $archivePath } | Should -Throw '*backslash*'
146+
Test-Path -LiteralPath $archivePath | Should -BeFalse
147+
}
148+
149+
It 'does not treat a raw backslash file record as a directory path' {
150+
$record = [pscustomobject]@{
151+
RelativePath = 'data\value.txt'
152+
Length = 1L
153+
Hash = [byte[]](0..31)
154+
}
155+
156+
{ Get-PSModuleContentDigest -File @($record) } | Should -Throw '*path*'
157+
}
158+
140159
It 'compares raw nupkg payload files without importing or changing consumer metadata' {
141160
$packagePath = Join-Path -Path $TestDrive -ChildPath 'TestModule.1.2.4.nupkg'
142161
$stream = [IO.File]::Create($packagePath)

‎.github/actions/Release-PSModule/tests/Release-PSModule.WhatIf.Tests.ps1‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,14 @@ Describe 'Release-PSModule WhatIf' {
256256
@($script:state.Release.assets).Count | Should -Be 0
257257
}
258258

259-
It 'rejects supplied PR context without a positive identity before release writes' {
259+
It 'rejects supplied PR context without a positive identity before release writes' -ForEach @(
260+
@{ Json = '{}' }
261+
@{ Json = '[]' }
262+
@{ Json = '[null]' }
263+
@{ Json = '[{"Number":42}]' }
264+
) {
260265
$env:PSMODULE_RELEASE_PSMODULE_INPUT_WhatIf = 'false'
261-
$env:PSMODULE_RELEASE_PSMODULE_INPUT_PullRequest = '{}'
266+
$env:PSMODULE_RELEASE_PSMODULE_INPUT_PullRequest = $Json
262267

263268
{ & $script:releaseScriptPath 1>$null 6>$null } | Should -Throw '*pull request*'
264269

0 commit comments

Comments
 (0)