fix #18670 quoteShellCommand, quoteShell, quoteShellWindows on windows (#18671)

This commit is contained in:
Timothee Cour 2021-08-12 07:50:08 -07:00 • committed by GitHub
commit 5c1304a418
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 6 deletions

View file

@ -1045,15 +1045,12 @@ proc expandTilde*(path: string): string {.
# TODO: handle `~bob` and `~bob/` which means home of bob # TODO: handle `~bob` and `~bob/` which means home of bob
result = path result = path
# TODO: consider whether quoteShellPosix, quoteShellWindows, quoteShell, quoteShellCommand
# belong in `strutils` instead; they are not specific to paths
proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} =
## Quote `s`, so it can be safely passed to Windows API. ## Quote `s`, so it can be safely passed to Windows API.
## ##
## Based on Python's `subprocess.list2cmdline`. ## Based on Python's `subprocess.list2cmdline`.
## See `this link <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_ ## See `this link <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_
## for more details. ## for more details.
let needQuote = {' ', '\t'} in s or s.len == 0 let needQuote = {' ', '\t'} in s or s.len == 0
result = "" result = ""
var backslashBuff = "" var backslashBuff = ""
@ -1064,8 +1061,8 @@ proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1"
if c == '\\': if c == '\\':
backslashBuff.add(c) backslashBuff.add(c)
elif c == '\"': elif c == '\"':
result.add(backslashBuff) for i in 0..<backslashBuff.len*2:
result.add(backslashBuff) result.add('\\')
backslashBuff.setLen(0) backslashBuff.setLen(0)
result.add("\\\"") result.add("\\\"")
else: else:
@ -1074,9 +1071,13 @@ proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1"
backslashBuff.setLen(0) backslashBuff.setLen(0)
result.add(c) result.add(c)
if backslashBuff.len > 0:
result.add(backslashBuff)
if needQuote: if needQuote:
result.add(backslashBuff)
result.add("\"") result.add("\"")
proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} =
## Quote ``s``, so it can be safely passed to POSIX shell. ## Quote ``s``, so it can be safely passed to POSIX shell.
const safeUnixChars = {'%', '+', '-', '.', '/', '_', ':', '=', '@', const safeUnixChars = {'%', '+', '-', '.', '/', '_', ':', '=', '@',

View file

@ -622,7 +622,18 @@ block: # quoteShellWindows
doAssert quoteShellWindows("aaa\"") == "aaa\\\"" doAssert quoteShellWindows("aaa\"") == "aaa\\\""
doAssert quoteShellWindows("") == "\"\"" doAssert quoteShellWindows("") == "\"\""
block: # quoteShellWindows block: # quoteShellCommand
when defined(windows):
doAssert quoteShellCommand(["a b c", "d", "e"]) == """"a b c" d e"""
doAssert quoteShellCommand(["""ab"c""", r"\", "d"]) == """ab\"c \ d"""
doAssert quoteShellCommand(["""ab"c""", """ \""", "d"]) == """ab\"c " \\" d"""
doAssert quoteShellCommand(["""a\\\b""", """de fg""", "h"]) == """a\\\b "de fg" h"""
doAssert quoteShellCommand(["""a\"b""", "c", "d"]) == """a\\\"b c d"""
doAssert quoteShellCommand(["""a\\b c""", "d", "e"]) == """"a\\b c" d e"""
doAssert quoteShellCommand(["""a\\b\ c""", "d", "e"]) == """"a\\b\ c" d e"""
doAssert quoteShellCommand(["ab", ""]) == """ab """""
block: # quoteShellPosix
doAssert quoteShellPosix("aaa") == "aaa" doAssert quoteShellPosix("aaa") == "aaa"
doAssert quoteShellPosix("aaa a") == "'aaa a'" doAssert quoteShellPosix("aaa a") == "'aaa a'"
doAssert quoteShellPosix("") == "''" doAssert quoteShellPosix("") == "''"