diff --git a/parser.go b/parser.go index b244962..f6768cb 100644 --- a/parser.go +++ b/parser.go @@ -115,7 +115,7 @@ func NewFromString(s string) (Line, error) { // Note: Don't use this functions to compare rules because the order of flags can be // different and different flags can have equal meanings. func (r Rule) String() (s string) { - s = fmt.Sprintf("-A %s %s", r.Chain, strings.Join(enquoteIfWS(r.Spec()), " ")) + s = fmt.Sprintf("-A %s %s", enquoteIfWS(r.Chain)[0], strings.Join(enquoteIfWS(r.Spec()...), " ")) if r.Counter != nil { s = fmt.Sprintf("%s %s", r.Counter.String(), s) } @@ -432,6 +432,9 @@ var ( ) func (p *Parser) parseDefault(lit string) (Line, error) { + if len(strings.TrimSpace(lit)) == 0 { + return nil, fmt.Errorf("nothing to parse in %q", lit) + } var r Policy r.Chain = string(regDefault.ReplaceAll([]byte(lit), []byte("$1"))) a := regDefault.ReplaceAll([]byte(lit), []byte("$2")) @@ -720,7 +723,7 @@ func (p *Parser) unscan(n int) { var hasWS *regexp.Regexp = regexp.MustCompile(`\s`) -func enquoteIfWS(s []string) []string { +func enquoteIfWS(s ...string) []string { ret := make([]string, len(s)) for i, e := range s { if hasWS.MatchString(e) { diff --git a/parser_test.go b/parser_test.go index 5da84fe..60f6acf 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1394,3 +1394,33 @@ func TestParser_ParseMore(t *testing.T) { } } } + +func FuzzParser_Parse(f *testing.F) { + f.Add(":hello ACCEPT [10:100]") + f.Fuzz(func(t *testing.T, input string) { + p := NewParser(strings.NewReader(input)) + for s, err := p.Parse(); err != io.EOF; s, err = p.Parse() { + if err == nil && s == nil { + t.Fatal("no error; no output") + } + if err != nil && s != nil { + t.Fatal("error and output") + } + if err != nil { + t.Skip() + } + { + p := NewParser(strings.NewReader(s.String())) + s2, err2 := p.Parse() + if err2 != nil { + t.Fatal(err2.Error()) + } + if !reflect.DeepEqual(s, s2) { + t.Logf("failed for %q", input) + t.Errorf("%q != %q", s.String(), s2.String()) + } + + } + } + }) +} diff --git a/scanner_test.go b/scanner_test.go index 8f19a67..011236e 100644 --- a/scanner_test.go +++ b/scanner_test.go @@ -1,6 +1,7 @@ package iptables_parser import ( + "fmt" "strings" "testing" ) @@ -31,13 +32,15 @@ func TestScanner_Scan(t *testing.T) { {s: "# 192.168.178.2/24", tok: COMMENTLINE, lit: " 192.168.178.2/24"}, {s: "I_test_rule-something", tok: IDENT, lit: "I_test_rule-something"}, } { - s := newScanner(strings.NewReader(tc.s)) - tok, lit := s.scan() - if tc.tok != tok { - t.Errorf("%d. %q token mismatch: exp=%q got=%q <%q>", i, tc.s, tc.tok, tok, lit) - } else if tc.lit != lit { - t.Errorf("%d. %q literal mismatch: exp=%q got=%q", i, tc.s, tc.lit, lit) - } + t.Run(fmt.Sprintf("%d. %q", i, tc.s), func(t *testing.T) { + s := newScanner(strings.NewReader(tc.s)) + tok, lit := s.scan() + if tc.tok != tok { + t.Errorf("%q token mismatch: exp=%q got=%q <%q>", tc.s, tc.tok, tok, lit) + } else if tc.lit != lit { + t.Errorf("%q literal mismatch: exp=%q got=%q", tc.s, tc.lit, lit) + } + }) } } diff --git a/testdata/fuzz/FuzzParser_Parse/55cbba0554d1434e b/testdata/fuzz/FuzzParser_Parse/55cbba0554d1434e new file mode 100644 index 0000000..0fc4026 --- /dev/null +++ b/testdata/fuzz/FuzzParser_Parse/55cbba0554d1434e @@ -0,0 +1,2 @@ +go test fuzz v1 +string("-A\" 0") diff --git a/testdata/fuzz/FuzzParser_Parse/82c2975c430ac608 b/testdata/fuzz/FuzzParser_Parse/82c2975c430ac608 new file mode 100644 index 0000000..0a66beb --- /dev/null +++ b/testdata/fuzz/FuzzParser_Parse/82c2975c430ac608 @@ -0,0 +1,2 @@ +go test fuzz v1 +string(":")