Skip to content

Commit da5035d

Browse files
author
Philip Sampaio
committed
Fix issues with escaping and arguments parsing
PowerShell have some weird rules for parsing arguments. We need to take care of strings that have spaces, because the space char is considered a separator for arguments. We need to surround these strings with double-quotes, but we also need to escape the quotes inside first. When it's a normal execution, this escaping is just "doubling" the double-quotes. But when the execution is for the `--pipe-to` argument, this needs to be an Unix escaping done twice for double-quotes.
1 parent 6c0899f commit da5035d

File tree

1 file changed

+19
-20
lines changed

1 file changed

+19
-20
lines changed

bin/elixir.ps1

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,19 @@ function NormalizeArg {
9090
$Items -join ","
9191
}
9292

93-
function QuotedString {
93+
function QuoteString {
9494
param(
95-
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
95+
[Parameter(ValueFromPipeline = $true)]
9696
[string] $Item
9797
)
9898

9999
# We surround the string with double quotes, in order to preserve its contents as
100100
# only one command arg.
101-
# This is needed because PowerShell will consider a new argument when it sees a
102-
# space char.
103-
if (-not $Item.StartsWith("`"") -and $Item.Contains(" ")) {
104-
"`"$Item`""
101+
# This is needed because PowerShell consider spaces as separator of arguments.
102+
# The double quotes around will be removed when PowerShell process the argument.
103+
# See: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.4#passing-quoted-strings-to-external-commands
104+
if ($Item.Contains(" ")) {
105+
'"' + $Item + '"'
105106
}
106107
else {
107108
$Item
@@ -121,7 +122,7 @@ for ($i = 0; $i -lt $Args.Count; $i++) {
121122

122123
switch ($Arg) {
123124
{ $_ -in @("-e", "-r", "-pr", "-pa", "-pz", "--eval", "--remsh", "--dot-iex", "--dbg") } {
124-
$private:NextArg = $Args[++$i] | NormalizeArg | QuotedString
125+
$private:NextArg = NormalizeArg($Args[++$i])
125126

126127
$ElixirParams.Add($Arg)
127128
$ElixirParams.Add($NextArg)
@@ -235,7 +236,7 @@ for ($i = 0; $i -lt $Args.Count; $i++) {
235236

236237
$ElixirParams.Add("--rpc-eval")
237238
$ElixirParams.Add($Key)
238-
$ElixirParams.Add("$(QuotedString $Value)")
239+
$ElixirParams.Add($Value)
239240
break
240241
}
241242

@@ -255,7 +256,7 @@ for ($i = 0; $i -lt $Args.Count; $i++) {
255256

256257
$ElixirParams.Add("-boot_var")
257258
$ElixirParams.Add($Key)
258-
$ElixirParams.Add("$(QuotedString $Value)")
259+
$ElixirParams.Add($Value)
259260
break
260261
}
261262

@@ -283,12 +284,7 @@ for ($i = 0; $i -lt $Args.Count; $i++) {
283284

284285
Default {
285286
$private:Normalized = NormalizeArg $Arg
286-
if ($Normalized.StartsWith("-")) {
287-
$AllOtherParams.Add($Normalized)
288-
}
289-
else {
290-
$AllOtherParams.Add("$(QuotedString $Normalized)")
291-
}
287+
$AllOtherParams.Add($Normalized)
292288
break
293289
}
294290
}
@@ -331,7 +327,8 @@ if ($ERTS_BIN) {
331327
}
332328

333329
if ($null -eq $RunErlPipe) {
334-
$ParamsPart = $AllParams -join " "
330+
# We double the double-quotes because they are going to be escaped by arguments parsing.
331+
$ParamsPart = $AllParams | ForEach-Object -Process { QuoteString($_ -replace "`"", "`"`"") }
335332
}
336333
else {
337334
$private:OrigBinPath = $BinPath
@@ -344,10 +341,12 @@ else {
344341

345342
$AllParams.Insert(0, $OrigBinPath)
346343

347-
# We only scape double-quotes because the command will be surrounded by double-quotes.
348-
$private:Escaped = $AllParams | ForEach-Object -Process { $_ -replace "`"", "\$&" }
344+
# We scape special chars using the Unix style of scaping, with "\".
345+
# But first we escape the double-quotes.
346+
$private:Escaped = $AllParams | ForEach-Object -Process { ($_ -replace "`"", "\`"") -replace "[^a-zA-Z0-9_/-]", "\$&" }
349347

350-
$ParamsPart = "-daemon `"$RunErlPipe/`" `"$RunErlLog/`" `"$([string]::Join(" ", $Escaped))`""
348+
# The args are surrounded here for the same reasons
349+
$ParamsPart = @("-daemon","`"$RunErlPipe/`"", "`"$RunErlLog/`"", "`"$($Escaped -join " ")`"")
351350
}
352351

353352
if ($Env:ELIXIR_CLI_DRY_RUN) {
@@ -358,6 +357,6 @@ else {
358357
$null = New-Item -Path "." -ItemType "directory" -Name "$RunErlPipe" -Force
359358
$null = New-Item -Path "." -ItemType "directory" -Name "$RunErlLog" -Force
360359
}
361-
$Output = Start-Process -FilePath $BinPath -ArgumentList "$ParamsPart" -NoNewWindow -Wait -PassThru
360+
$Output = Start-Process -FilePath $BinPath -ArgumentList $ParamsPart -NoNewWindow -Wait -PassThru
362361
exit $Output.ExitCode
363362
}

0 commit comments

Comments
 (0)