fuzz testing and bug fixes

This commit is contained in:
Matt Jaffee 2018-06-14 17:40:28 -05:00
parent 2ddc2ceeeb
commit 1e05920742
No known key found for this signature in database
GPG key ID: 08A3DFFF987B11BF
86 changed files with 1072 additions and 686 deletions

View file

@ -653,7 +653,7 @@ func TestHandler_Query_ErrParse(t *testing.T) {
h.ServeHTTP(w, test.MustNewHTTPRequest("POST", "/index/idx0/query?slices=0,1", strings.NewReader("bad_fn(")))
if w.Code != gohttp.StatusBadRequest {
t.Fatalf("unexpected status code: %d", w.Code)
} else if body := w.Body.String(); body != `{"error":"parsing: parsing: \nparse error near PegText (line 1 symbol 1 - line 1 symbol 4):\n\"bad\"\n"}`+"\n" {
} else if body := w.Body.String(); body != `{"error":"parsing: parsing: \nparse error near open (line 1 symbol 7 - line 1 symbol 8):\n\"(\"\n"}`+"\n" {
t.Fatalf("unexpected body: \n%s", body)
}
}

View file

@ -72,11 +72,8 @@ func (q *Query) addVal(val interface{}) {
return
}
if q.lastCond != ILLEGAL {
if val != nil || q.lastCond != NEQ {
panic(fmt.Sprintf("can't add val %s with condition %s", val, q.lastCond))
}
call.Args[q.lastField] = &Condition{
Op: NEQ,
Op: q.lastCond,
Value: val,
}
} else {

8
pql/fuzz/README.txt Normal file
View file

@ -0,0 +1,8 @@
See https://github.com/dvyukov/go-fuzz
Quickstart:
go get -u github.com/dvyukov/go-fuzz/...
go-fuzz-build github.com/pilosa/pilosa/pql
go-fuzz -bin=./pql-fuzz.zip -workdir=$GOPATH/src/github.com/pilosa/pilosa/pql/fuzz

View file

@ -0,0 +1 @@
e(rT03

View file

@ -0,0 +1 @@
e(d=f2002-01-01T03:00

View file

@ -0,0 +1 @@
e(other!=-2)

1
pql/fuzz/corpus/1 Normal file
View file

@ -0,0 +1 @@
Bitmap()

1
pql/fuzz/corpus/10 Normal file
View file

@ -0,0 +1 @@
Bitmap(row=10, field=f)

1
pql/fuzz/corpus/11 Normal file
View file

@ -0,0 +1 @@
Difference(Bitmap(row=10), Bitmap(row=11))

View file

@ -0,0 +1 @@
Range(foo<0)

1
pql/fuzz/corpus/12 Normal file
View file

@ -0,0 +1 @@
Difference()

1
pql/fuzz/corpus/13 Normal file
View file

@ -0,0 +1 @@
Intersect(Bitmap(row=10), Bitmap(row=11))

View file

@ -0,0 +1 @@
SV(invalid_column_name=10,f=100)

1
pql/fuzz/corpus/14 Normal file
View file

@ -0,0 +1 @@
Intersect()

1
pql/fuzz/corpus/15 Normal file
View file

@ -0,0 +1 @@
Union(Bitmap(row=10), Bitmap(row=11))

1
pql/fuzz/corpus/16 Normal file
View file

@ -0,0 +1 @@
Union()

1
pql/fuzz/corpus/17 Normal file
View file

@ -0,0 +1 @@
Xor(Bitmap(row=10), Bitmap(row=11))

1
pql/fuzz/corpus/18 Normal file
View file

@ -0,0 +1 @@
Count(Bitmap(row=10, field=f))

1
pql/fuzz/corpus/19 Normal file
View file

@ -0,0 +1 @@
SetBit(row=11, field=f, col=1)

1
pql/fuzz/corpus/2 Normal file
View file

@ -0,0 +1 @@
Union( Bitmap() , Count() )

1
pql/fuzz/corpus/20 Normal file
View file

@ -0,0 +1 @@
SetValue(col=10, f=25)

1
pql/fuzz/corpus/21 Normal file
View file

@ -0,0 +1 @@
SetValue(invalid_column_name=10, f=100)

1
pql/fuzz/corpus/22 Normal file
View file

@ -0,0 +1 @@
SetRowAttrs(row=10, field=f, baz=123, bat=true)

5
pql/fuzz/corpus/23 Normal file
View file

@ -0,0 +1,5 @@
SetBit(field=f, row=1, col=2, timestamp="1999-12-31T00:00")
SetBit(field=f, row=1, col=7, timestamp="2002-01-01T02:00")
SetBit(field=f, row=1, col=2, timestamp="1999-12-30T00:00")

1
pql/fuzz/corpus/24 Normal file
View file

@ -0,0 +1 @@
Range(row=1, field=f, start="1999-12-31T00:00", end="2002-01-01T03:00")

2
pql/fuzz/corpus/25 Normal file
View file

@ -0,0 +1,2 @@
Range(foo == 20)

1
pql/fuzz/corpus/26 Normal file
View file

@ -0,0 +1 @@
Range(other != null)

1
pql/fuzz/corpus/27 Normal file
View file

@ -0,0 +1 @@
Range(foo != 20)

View file

@ -0,0 +1 @@
N(p(d=0,l=other), d=f,n=3)

1
pql/fuzz/corpus/28 Normal file
View file

@ -0,0 +1 @@
Range(other != -20)

1
pql/fuzz/corpus/29 Normal file
View file

@ -0,0 +1 @@
Range(foo < 20)

1
pql/fuzz/corpus/3 Normal file
View file

@ -0,0 +1 @@
Count( Bitmap( id=100))

1
pql/fuzz/corpus/30 Normal file
View file

@ -0,0 +1 @@
Range(foo <= 20)

1
pql/fuzz/corpus/31 Normal file
View file

@ -0,0 +1 @@
SetRowAttrs(row=10, field=f, baz=12.3, bat=.21, bak=-.27, zaz=-0.27 , q=0, zoo="0", do='0')

View file

@ -0,0 +1 @@
t( p( ))

View file

@ -0,0 +1 @@
SetRowAttrs(row=10,field=f,baz=123,bat=true)

View file

@ -0,0 +1,2 @@
e(o == 0)

View file

@ -0,0 +1 @@
e(r!=-2)

View file

@ -0,0 +1 @@
MyCall( y=-12.25, o= -13)

1
pql/fuzz/corpus/4 Normal file
View file

@ -0,0 +1 @@
MyCall( key= value, foo="bar", age = 12 , bool0=true, bool1=false, x=null )

View file

@ -0,0 +1 @@
t(p(w=1,l=f))

1
pql/fuzz/corpus/5 Normal file
View file

@ -0,0 +1 @@
MyCall( key=12.25, foo= 13.167, bar=2., baz=0.9)

View file

@ -0,0 +1 @@
e(row=1,field=f,start="1999-12-31T00:00",end="2002-01-01T03:00")

View file

@ -0,0 +1 @@
MyCall(ke=foo, x =5, y >= 100, z >< [4,8], m != null)

View file

@ -0,0 +1 @@
SetValue(invalid_column_name=10,f=100)

View file

@ -0,0 +1 @@
Range(other!=null)

1
pql/fuzz/corpus/6 Normal file
View file

@ -0,0 +1 @@
MyCall( key=-12.25, foo= -13)

View file

@ -0,0 +1 @@
tRowAttrs(row=1, field=f, baz=13,bat=true)

View file

@ -0,0 +1 @@
e(w=:

1
pql/fuzz/corpus/7 Normal file
View file

@ -0,0 +1 @@
TopN(field="f", ids=[0,10,30])

View file

@ -0,0 +1 @@
n(p() , C

View file

@ -0,0 +1 @@
t(p(d=100))

View file

@ -0,0 +1 @@
U(B(,C

View file

@ -0,0 +1 @@
e(w=12002

View file

@ -0,0 +1 @@
e(o <= 0)

View file

@ -0,0 +1 @@
t(p(w=0), p(w=1))

View file

@ -0,0 +1 @@
n(p(),C(

1
pql/fuzz/corpus/8 Normal file
View file

@ -0,0 +1 @@
TopN(Bitmap(id=100, field=other), field=f, n=3)

View file

@ -0,0 +1 @@
C(y=12.25,o=13.167,r=2.,z=0.9)

1
pql/fuzz/corpus/9 Normal file
View file

@ -0,0 +1 @@
MyCall(key=foo, x == 12.25, y >= 100, z >< [4,8], m != null)

View file

@ -0,0 +1 @@
t(p( ))

View file

@ -0,0 +1 @@
e(invalid_column_name<0,f=0)

View file

@ -0,0 +1 @@
tV(f=5)

View file

@ -0,0 +1 @@
t(Ba(w=0,d=f))

View file

@ -0,0 +1 @@
Range(o < 0)

View file

@ -0,0 +1 @@
n()

View file

@ -0,0 +1 @@
Intersect(Bitmap(row=10),Bitmap(row=11))

View file

@ -0,0 +1 @@
Cl( k=-12.25, f= -13)

View file

@ -0,0 +1 @@
e(o<0)

View file

@ -0,0 +1 @@
Difference(Bitmap(row=10),Bitmap(row=11))

View file

@ -0,0 +1 @@
j(w=10375035658,t=R)

View file

@ -0,0 +1 @@
Range(other!=l)

View file

@ -0,0 +1 @@
e(o<=0)

View file

@ -0,0 +1 @@
e(w=T

View file

@ -0,0 +1 @@
l(key=oo, x == 12.25, y >= 100, z >< [4,8], m != null)

View file

@ -0,0 +1 @@
SB(ow=1, f=f, c=1)

View file

@ -0,0 +1 @@
Setalue(invalidcolumnnamf=0)

View file

@ -0,0 +1 @@
N(field="f",ids=[0,10,30])

View file

@ -0,0 +1 @@
U( B() , C() )

View file

@ -0,0 +1 @@
Range(r!=null)

View file

@ -190,5 +190,4 @@ func TestParser_Parse(t *testing.T) {
t.Fatalf("unexpected call: %#v", q.Calls[0])
}
})
}

View file

@ -71,7 +71,7 @@ func (s *Scanner) Scan() (tok Token, pos Pos, lit string) {
return NEQ, pos, "!="
}
s.unread()
return ASSIGN, pos, string(ch)
return ILLEGAL, pos, string(ch)
case '<':
if next := s.read(); next == '=' {
return LTE, pos, "<="

115
pql/parser_fuzz.go Normal file
View file

@ -0,0 +1,115 @@
// +build gofuzz
package pql
import (
"bytes"
"fmt"
"reflect"
"github.com/pilosa/pilosa/pql/internal/oldpql"
"github.com/pkg/errors"
)
func Fuzz(data []byte) int {
p1 := NewParser(bytes.NewReader(data))
q1, err1 := p1.Parse()
p2 := oldpql.NewParser(bytes.NewReader(data))
q2, err2 := p2.Parse()
if err1 != nil && err2 != nil {
return 0 // both error - this is fine
}
if err1 != nil || err2 != nil {
// error in one but not both - need to know this
panic(fmt.Sprintf("Query: '%s' errored one but not both.\n%v\n%v\n", data, err1, err2))
}
// if parsers got different results
if err := queriesEqual(q1, q2); err != nil {
panic(fmt.Sprintf(`Query: '%s' parsed, but got different results:
Result New (string)
%s
Result New (hashv)
%#v
Result Old (string)
%s
Result Old (hashv)
%#v
err:
%v
`, data, q1, q1, q2, q2, err))
}
// both queries parsed succesfully and got equivalent results
return 1
}
func queriesEqual(q1 *Query, q2 *oldpql.Query) (err error) {
if q1.String() != q2.String() {
defer func() {
// golang black magic
if err == nil {
err = errors.New("string reps unequal")
} else {
err = errors.Wrap(err, "string reps unequal")
}
}()
}
if len(q1.Calls) != len(q2.Calls) {
return errors.Errorf("call lengths unequal: %d and %d", len(q1.Calls), len(q2.Calls))
}
for i, c1 := range q1.Calls {
c2 := q2.Calls[i]
if err := callsEqual(c1, c2); err != nil {
return errors.Wrapf(err, "calls at %d not equal", i)
}
}
return nil
}
func callsEqual(c1 *Call, c2 *oldpql.Call) error {
if err := argsEqual(c1.Args, c2.Args); err != nil {
return errors.Wrap(err, "args unequal")
}
if c1.Name != c2.Name {
return errors.Errorf("names unequal '%s' != '%s'", c1.Name, c2.Name)
}
if len(c1.Children) != len(c2.Children) {
return errors.Errorf("different child lengths %d and %d", len(c1.Children), len(c2.Children))
}
for i, child1 := range c1.Children {
child2 := c2.Children[i]
if err := callsEqual(child1, child2); err != nil {
return errors.Wrapf(err, "children at %d not equal", i)
}
}
return nil
}
func argsEqual(a1 map[string]interface{}, a2 map[string]interface{}) error {
if len(a1) != len(a2) {
return errors.Errorf("lengths unequal %d and %d", len(a1), len(a2))
}
for k, v1 := range a1 {
v2 := a1[k]
if c1, ok := v1.(Condition); ok {
if c2, ok := v2.(oldpql.Condition); ok {
if int(c1.Op) != int(c2.Op) {
return errors.Errorf("condition ops unequal %d %d", c1, c2)
}
if !reflect.DeepEqual(c1.Value, c2.Value) {
return errors.Errorf("condition values unequal '%v' '%v'", c1.Value, c2.Value)
}
continue
}
return errors.Errorf("values at %s unequal '%v' '%v'", k, v1, v2)
}
if !reflect.DeepEqual(v1, v2) {
return errors.Errorf("values at %s unequal '%v' '%v'", k, v1, v2)
}
}
return nil
}

View file

@ -6,10 +6,10 @@ type PQL Peg {
Calls <- Call* !.
Call <- newline* < [[A-Z]]+ > { p.startCall(buffer[begin:end] ) } open args close newline* { p.endCall() }
args <- arg (comma args)? sp / sp
arg <- ( Call
/ field sp '=' sp value
Call <- whitesp < IDENT > { p.startCall(buffer[begin:end] ) } open allargs comma? close whitesp { p.endCall() }
allargs <- Call (comma Call)* (comma args)? / comma? args / sp
args <- arg (comma args)? sp
arg <- ( field sp '=' sp value
/ field sp COND sp value
)
COND <- ( '><' { p.addBTWN() }
@ -25,9 +25,9 @@ value <- ( item
/ lbrack { p.startList() } list rbrack { p.endList() }
)
list <- item (comma list)?
item <- ( 'null' { p.addVal(nil) }
/ 'true' { p.addVal(true) }
/ 'false' { p.addVal(false) }
item <- ( 'null' &(comma / sp close) { p.addVal(nil) }
/ 'true' &(comma / sp close) { p.addVal(true) }
/ 'false' &(comma / sp close) { p.addVal(false) }
/ < '-'? [0-9]+ ('.'[0-9]*)? > { p.addNumVal(buffer[begin:end]) }
/ < '-'? '.'[0-9]+ > { p.addNumVal(buffer[begin:end]) }
/ < ([[A-Z]] / [0-9] / '-' / '_' / ':')+ > { p.addVal(buffer[begin:end]) }
@ -44,4 +44,5 @@ sp <- ( ' ' / '\t' )*
comma <- sp ',' sp
lbrack <- '[' sp
rbrack <- sp ']' sp
newline <- sp '\n' sp
whitesp <- ( ' ' / '\t' / '\n' )*
IDENT <- [[A-Z]] ([[A-Z]] / [0-9] / '-' / '_' / '.')*

File diff suppressed because it is too large Load diff

View file

@ -20,4 +20,27 @@ SetBit(Union(Zitmap(row==4), Intersect(Qitmap(blah>4), Ritmap(field="http://zoo9
if err == nil {
t.Fatalf("should have been an error because of the interior unescaped double quote")
}
q, err := ParseString("TopN(Bitmap(id==other), field=f, n=0)")
if err != nil {
t.Fatalf("should have parsed: %v", err)
}
if q.String() != `TopN(Bitmap(id == "other"), field="f", n=0)` {
t.Fatalf("Failed, got: %s", q)
}
q, err = ParseString("C(a=falsen0)")
if err != nil {
t.Fatalf("falsen0 should have been parsed as a string")
}
q, err = ParseString("Bitmap(row=4, did==other)")
if err != nil {
t.Fatalf("should have parsed: %v", err)
}
if q.String() != `Bitmap(did == "other", row=4)` {
t.Fatalf("got %s", q)
}
}