Skip to content

Commit 92eab20

Browse files
committed
syntax: extend FuzzQuote to check with our parser
That is, verify that our parser also parses the quoted string as a single word in a simple command. The updated fuzzer quickly found that we forgot about the empty string. An empty string must be quoted, as otherwise it expands to zero fields. The printf verification did not catch this.
1 parent 5c97fec commit 92eab20

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

syntax/fuzz_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"os/exec"
1313
"strings"
1414
"testing"
15+
16+
qt "github.com/frankban/quicktest"
1517
)
1618

1719
func FuzzQuote(f *testing.F) {
@@ -57,8 +59,14 @@ func FuzzQuote(f *testing.F) {
5759
panic(fmt.Sprintf("unknown lang variant: %d", lang))
5860
}
5961

60-
// TODO: Also double-check with our parser.
61-
// That should allow us to fuzz Bats too, for instance.
62+
f, err := NewParser(Variant(lang)).Parse(strings.NewReader(quoted), "")
63+
if err != nil {
64+
t.Fatalf("parse error on %q quoted as %s: %v", s, quoted, err)
65+
}
66+
qt.Assert(t, len(f.Stmts), qt.Equals, 1, qt.Commentf("in: %q, quoted: %s", s, quoted))
67+
call, ok := f.Stmts[0].Cmd.(*CallExpr)
68+
qt.Assert(t, ok, qt.IsTrue, qt.Commentf("in: %q, quoted: %s", s, quoted))
69+
qt.Assert(t, len(call.Args), qt.Equals, 1, qt.Commentf("in: %q, quoted: %s", s, quoted))
6270

6371
// Beware that this might run arbitrary code
6472
// if Quote is too naive and allows ';' or '$'.

syntax/quote.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ const (
4646
// Some strings do not require any quoting and are returned unchanged.
4747
// Those strings can be directly surrounded in single quotes as well.
4848
func Quote(s string, lang LangVariant) (string, error) {
49+
if s == "" {
50+
// Special case; an empty string must always be quoted,
51+
// as otherwise it expands to zero fields.
52+
return "''", nil
53+
}
4954
shellChars := false
5055
nonPrintable := false
5156
offs := 0

syntax/quote_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestQuote(t *testing.T) {
1616
lang LangVariant
1717
want interface{}
1818
}{
19-
{"", LangBash, ``},
19+
{"", LangBash, `''`},
2020
{"\a", LangBash, `$'\a'`},
2121
{"\b", LangBash, `$'\b'`},
2222
{"\f", LangBash, `$'\f'`},

0 commit comments

Comments
 (0)