Skip to content

Commit

Permalink
syntax: extend FuzzQuote to check with our parser
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mvdan committed Oct 8, 2021
1 parent 5c97fec commit 92eab20
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 3 deletions.
12 changes: 10 additions & 2 deletions syntax/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"os/exec"
"strings"
"testing"

qt "github.com/frankban/quicktest"
)

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

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

// Beware that this might run arbitrary code
// if Quote is too naive and allows ';' or '$'.
Expand Down
5 changes: 5 additions & 0 deletions syntax/quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ const (
// Some strings do not require any quoting and are returned unchanged.
// Those strings can be directly surrounded in single quotes as well.
func Quote(s string, lang LangVariant) (string, error) {
if s == "" {
// Special case; an empty string must always be quoted,
// as otherwise it expands to zero fields.
return "''", nil
}
shellChars := false
nonPrintable := false
offs := 0
Expand Down
2 changes: 1 addition & 1 deletion syntax/quote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestQuote(t *testing.T) {
lang LangVariant
want interface{}
}{
{"", LangBash, ``},
{"", LangBash, `''`},
{"\a", LangBash, `$'\a'`},
{"\b", LangBash, `$'\b'`},
{"\f", LangBash, `$'\f'`},
Expand Down

0 comments on commit 92eab20

Please sign in to comment.