@@ -24,74 +24,87 @@ var ForkLock sync.RWMutex
24
24
// - finally, s is wrapped with double quotes (arg -> "arg"),
25
25
// but only if there is space or tab inside s.
26
26
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 {
27
42
if len (s ) == 0 {
28
- return " \" \" "
43
+ return append ( b , `""` ... )
29
44
}
30
- n := len (s )
45
+
46
+ needsBackslash := false
31
47
hasSpace := false
32
48
for i := 0 ; i < len (s ); i ++ {
33
49
switch s [i ] {
34
50
case '"' , '\\' :
35
- n ++
51
+ needsBackslash = true
36
52
case ' ' , '\t' :
37
53
hasSpace = true
38
54
}
39
55
}
40
- if hasSpace {
41
- n += 2
56
+
57
+ if ! needsBackslash && ! hasSpace {
58
+ // No special handling required; normal case.
59
+ return append (b , s ... )
42
60
}
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 , '"' )
45
66
}
46
67
47
- qs := make ([]byte , n )
48
- j := 0
49
68
if hasSpace {
50
- qs [j ] = '"'
51
- j ++
69
+ b = append (b , '"' )
52
70
}
53
71
slashes := 0
54
72
for i := 0 ; i < len (s ); i ++ {
55
- switch s [i ] {
73
+ c := s [i ]
74
+ switch c {
56
75
default :
57
76
slashes = 0
58
- qs [j ] = s [i ]
59
77
case '\\' :
60
78
slashes ++
61
- qs [j ] = s [i ]
62
79
case '"' :
63
80
for ; slashes > 0 ; slashes -- {
64
- qs [j ] = '\\'
65
- j ++
81
+ b = append (b , '\\' )
66
82
}
67
- qs [j ] = '\\'
68
- j ++
69
- qs [j ] = s [i ]
83
+ b = append (b , '\\' )
70
84
}
71
- j ++
85
+ b = append ( b , c )
72
86
}
73
87
if hasSpace {
74
88
for ; slashes > 0 ; slashes -- {
75
- qs [j ] = '\\'
76
- j ++
89
+ b = append (b , '\\' )
77
90
}
78
- qs [j ] = '"'
79
- j ++
91
+ b = append (b , '"' )
80
92
}
81
- return string (qs [:j ])
93
+
94
+ return b
82
95
}
83
96
84
97
// makeCmdLine builds a command line out of args by escaping "special"
85
98
// characters and joining the arguments with spaces.
86
99
func makeCmdLine (args []string ) string {
87
- var s string
100
+ var b [] byte
88
101
for _ , v := range args {
89
- if s != "" {
90
- s += " "
102
+ if len ( b ) > 0 {
103
+ b = append ( b , ' ' )
91
104
}
92
- s += EscapeArg ( v )
105
+ b = appendEscapeArg ( b , v )
93
106
}
94
- return s
107
+ return string ( b )
95
108
}
96
109
97
110
// createEnvBlock converts an array of environment strings into
0 commit comments