Skip to content

Commit e2951fc

Browse files
committed
Fix dollarQuote state management in shellwords.go
Updated dollarQuote handling to prevent toggling on bare ')' characters.
1 parent 551a1d0 commit e2951fc

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

shellwords.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,23 +200,50 @@ loop:
200200
backtick = ""
201201
backQuote = !backQuote
202202
}
203+
203204
case ')':
204205
if !singleQuoted && !doubleQuoted && !backQuote {
205206
if p.ParseBacktick {
206-
if dollarQuote {
207-
out, err := shellRun(backtick, p.Dir)
208-
if err != nil {
209-
return nil, err
210-
}
211-
buf = buf[:len(buf)-len(backtick)-2] + out
207+
// Hardened fix:
208+
// A bare ')' must never open dollarQuote state.
209+
// Only close an already-open $(...) region.
210+
if !dollarQuote {
211+
buf += string(r)
212+
got = argSingle
213+
continue
214+
}
215+
216+
out, err := shellRun(backtick, p.Dir)
217+
if err != nil {
218+
return nil, err
219+
}
220+
221+
// Defensive guard: valid $(...) implies the buffer must contain
222+
// the "$(" prefix plus the collected command body.
223+
if len(buf) < len(backtick)+2 {
224+
return nil, errors.New("invalid command line string")
212225
}
226+
227+
buf = buf[:len(buf)-len(backtick)-2] + out
213228
backtick = ""
214-
dollarQuote = !dollarQuote
229+
dollarQuote = false
215230
continue
216231
}
232+
233+
// Default mode:
234+
// Do not toggle dollarQuote on a bare ')'.
235+
// Treat it as a literal character.
236+
if !dollarQuote {
237+
buf += string(r)
238+
got = argSingle
239+
continue
240+
}
241+
217242
backtick = ""
218-
dollarQuote = !dollarQuote
243+
dollarQuote = false
244+
continue
219245
}
246+
220247
case '(':
221248
if !singleQuoted && !doubleQuoted && !backQuote {
222249
if !dollarQuote && strings.HasSuffix(buf, "$") {
@@ -227,6 +254,7 @@ loop:
227254
return nil, errors.New("invalid command line string")
228255
}
229256
}
257+
230258
case '"':
231259
if !singleQuoted && !dollarQuote {
232260
if doubleQuoted {
@@ -235,6 +263,7 @@ loop:
235263
doubleQuoted = !doubleQuoted
236264
continue
237265
}
266+
238267
case '\'':
239268
if !doubleQuoted && !dollarQuote {
240269
if singleQuoted {
@@ -243,6 +272,7 @@ loop:
243272
singleQuoted = !singleQuoted
244273
continue
245274
}
275+
246276
case ';', '&', '|', '<', '>':
247277
if !(escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote) {
248278
if r == '>' && len(buf) > 0 {

0 commit comments

Comments
 (0)