summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2021-08-12 07:50:08 -0700
committerGitHub <noreply@github.com>2021-08-12 16:50:08 +0200
commit5c1304a4181596e764b05679cd8a0044ab3398dd (patch)
treea68e7a65e1725012e38d8a0acea9857742f0a5b2
parent018465a2345b2d11f7d1d711010d97e636af98d0 (diff)
downloadNim-5c1304a4181596e764b05679cd8a0044ab3398dd.tar.gz
fix #18670 quoteShellCommand, quoteShell, quoteShellWindows on windows (#18671)
-rw-r--r--lib/pure/os.nim11
-rw-r--r--tests/stdlib/tos.nim13
2 files changed, 18 insertions, 6 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index fd618e93c..cfdacdb3c 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1045,15 +1045,12 @@ proc expandTilde*(path: string): string {.
     # TODO: handle `~bob` and `~bob/` which means home of bob
     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".} =
   ## Quote `s`, so it can be safely passed to Windows API.
   ##
   ## Based on Python's `subprocess.list2cmdline`.
   ## See `this link <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_
   ## for more details.
-
   let needQuote = {' ', '\t'} in s or s.len == 0
   result = ""
   var backslashBuff = ""
@@ -1064,8 +1061,8 @@ proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1"
     if c == '\\':
       backslashBuff.add(c)
     elif c == '\"':
-      result.add(backslashBuff)
-      result.add(backslashBuff)
+      for i in 0..<backslashBuff.len*2:
+        result.add('\\')
       backslashBuff.setLen(0)
       result.add("\\\"")
     else:
@@ -1074,9 +1071,13 @@ proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1"
         backslashBuff.setLen(0)
       result.add(c)
 
+  if backslashBuff.len > 0:
+    result.add(backslashBuff)
   if needQuote:
+    result.add(backslashBuff)
     result.add("\"")
 
+
 proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} =
   ## Quote ``s``, so it can be safely passed to POSIX shell.
   const safeUnixChars = {'%', '+', '-', '.', '/', '_', ':', '=', '@',
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index dcb2d44f4..b7816fd41 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -622,7 +622,18 @@ block: # quoteShellWindows
   doAssert quoteShellWindows("aaa\"") == "aaa\\\""
   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 a") == "'aaa a'"
   doAssert quoteShellPosix("") == "''"