Skip to content

Commit 4922585

Browse files
syscall: rewrite Windows makeCmdLine to use []byte
It's faster to append to a []byte and only convert to string at the end then it is to build up a string by concatenating characters. Fixes #41825 Change-Id: I45ddf77dcc62726c919f0533c95d483cee8ba366 Reviewed-on: https://go-review.googlesource.com/c/go/+/259978 Trust: Ian Lance Taylor <[email protected]> Trust: Alex Brainman <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Alex Brainman <[email protected]>
1 parent ccf89be commit 4922585

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

src/syscall/exec_windows.go

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,74 +24,87 @@ var ForkLock sync.RWMutex
2424
// - finally, s is wrapped with double quotes (arg -> "arg"),
2525
// but only if there is space or tab inside s.
2626
func EscapeArg(s string) string {
27+
for i := 0; i < len(s); i++ {
28+
switch s[i] {
29+
case '"', '\\', ' ', '\t':
30+
// Some escaping required.
31+
b := make([]byte, 0, len(s)+2)
32+
b = appendEscapeArg(b, s)
33+
return string(b)
34+
}
35+
}
36+
return s
37+
}
38+
39+
// appendEscapeArg escapes the string s, as per escapeArg,
40+
// appends the result to b, and returns the updated slice.
41+
func appendEscapeArg(b []byte, s string) []byte {
2742
if len(s) == 0 {
28-
return "\"\""
43+
return append(b, `""`...)
2944
}
30-
n := len(s)
45+
46+
needsBackslash := false
3147
hasSpace := false
3248
for i := 0; i < len(s); i++ {
3349
switch s[i] {
3450
case '"', '\\':
35-
n++
51+
needsBackslash = true
3652
case ' ', '\t':
3753
hasSpace = true
3854
}
3955
}
40-
if hasSpace {
41-
n += 2
56+
57+
if !needsBackslash && !hasSpace {
58+
// No special handling required; normal case.
59+
return append(b, s...)
4260
}
43-
if n == len(s) {
44-
return s
61+
if !needsBackslash {
62+
// hasSpace is true, so we need to quote the string.
63+
b = append(b, '"')
64+
b = append(b, s...)
65+
return append(b, '"')
4566
}
4667

47-
qs := make([]byte, n)
48-
j := 0
4968
if hasSpace {
50-
qs[j] = '"'
51-
j++
69+
b = append(b, '"')
5270
}
5371
slashes := 0
5472
for i := 0; i < len(s); i++ {
55-
switch s[i] {
73+
c := s[i]
74+
switch c {
5675
default:
5776
slashes = 0
58-
qs[j] = s[i]
5977
case '\\':
6078
slashes++
61-
qs[j] = s[i]
6279
case '"':
6380
for ; slashes > 0; slashes-- {
64-
qs[j] = '\\'
65-
j++
81+
b = append(b, '\\')
6682
}
67-
qs[j] = '\\'
68-
j++
69-
qs[j] = s[i]
83+
b = append(b, '\\')
7084
}
71-
j++
85+
b = append(b, c)
7286
}
7387
if hasSpace {
7488
for ; slashes > 0; slashes-- {
75-
qs[j] = '\\'
76-
j++
89+
b = append(b, '\\')
7790
}
78-
qs[j] = '"'
79-
j++
91+
b = append(b, '"')
8092
}
81-
return string(qs[:j])
93+
94+
return b
8295
}
8396

8497
// makeCmdLine builds a command line out of args by escaping "special"
8598
// characters and joining the arguments with spaces.
8699
func makeCmdLine(args []string) string {
87-
var s string
100+
var b []byte
88101
for _, v := range args {
89-
if s != "" {
90-
s += " "
102+
if len(b) > 0 {
103+
b = append(b, ' ')
91104
}
92-
s += EscapeArg(v)
105+
b = appendEscapeArg(b, v)
93106
}
94-
return s
107+
return string(b)
95108
}
96109

97110
// createEnvBlock converts an array of environment strings into

0 commit comments

Comments
 (0)