Skip to content

Commit aa32c6d

Browse files
committed
Add fuzz test and fix parser bugs
1 parent b988cac commit aa32c6d

File tree

5 files changed

+48
-12
lines changed

5 files changed

+48
-12
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ bin/
1717
.idea/
1818
release
1919
*.pprof
20+
query/testdata

query/lexer.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (l *Lexer) Split() []*Token {
141141
tokLen++
142142
break
143143
}
144-
curr = l.Query[tokStart : tokStart+tokLen]
144+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
145145
if token := buildToken(curr, tokStartPos); token != nil {
146146
ret = append(ret, token)
147147
}
@@ -156,7 +156,7 @@ func (l *Lexer) Split() []*Token {
156156
tokStart = i + 1
157157
} else if strStartChar == char {
158158
strStart = false
159-
curr = l.Query[tokStart : tokStart+tokLen]
159+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
160160
token := &Token{
161161
Tp: STRING,
162162
Data: curr,
@@ -175,7 +175,7 @@ func (l *Lexer) Split() []*Token {
175175
tokStart = i + 1
176176
} else if strStartChar == char {
177177
strStart = false
178-
curr = l.Query[tokStart : tokStart+tokLen]
178+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
179179
token := &Token{
180180
Tp: NAME,
181181
Data: curr,
@@ -191,7 +191,7 @@ func (l *Lexer) Split() []*Token {
191191
tokLen++
192192
break
193193
}
194-
curr = l.Query[tokStart : tokStart+tokLen]
194+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
195195
if token := buildToken(curr, tokStartPos); token != nil {
196196
ret = append(ret, token)
197197
}
@@ -271,7 +271,7 @@ func (l *Lexer) Split() []*Token {
271271
tokLen++
272272
break
273273
}
274-
curr = l.Query[tokStart : tokStart+tokLen]
274+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
275275
token := buildToken(curr, tokStartPos)
276276
if token != nil {
277277
ret = append(ret, token)
@@ -317,7 +317,7 @@ func (l *Lexer) Split() []*Token {
317317
tokLen++
318318
break
319319
}
320-
curr = l.Query[tokStart : tokStart+tokLen]
320+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
321321
token := buildToken(curr, tokStartPos)
322322
if token != nil {
323323
ret = append(ret, token)
@@ -337,7 +337,7 @@ func (l *Lexer) Split() []*Token {
337337
prev = char
338338
}
339339
if tokLen > 0 {
340-
curr = l.Query[tokStart : tokStart+tokLen]
340+
curr = l.Query[tokStart : tokStart+min(tokLen, l.Length-tokStart)]
341341
if token := buildToken(curr, tokStartPos); token != nil {
342342
ret = append(ret, token)
343343
}
@@ -425,5 +425,4 @@ func buildToken(curr string, pos int) *Token {
425425
token.Tp = NAME
426426
return token
427427
}
428-
return nil
429428
}

query/optimizer.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func (o *Optimizer) buildFinalPlan(t Txn, fp Plan) (FinalPlan, error) {
156156
return ffp, nil
157157
}
158158

159-
func (o *Optimizer) BuildPlan(t Txn) (FinalPlan, error) {
159+
func (o *Optimizer) buildPlan(t Txn) (FinalPlan, error) {
160160
err := o.init()
161161
if err != nil {
162162
return nil, err
@@ -184,6 +184,14 @@ func (o *Optimizer) BuildPlan(t Txn) (FinalPlan, error) {
184184
if err != nil {
185185
return nil, err
186186
}
187+
return ret, nil
188+
}
189+
190+
func (o *Optimizer) BuildPlan(t Txn) (FinalPlan, error) {
191+
ret, err := o.buildPlan(t)
192+
if err != nil {
193+
return nil, err
194+
}
187195
err = ret.Init()
188196
if err != nil {
189197
return nil, err

query/parser.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ func (p *Parser) parseSelect() (*SelectStmt, error) {
377377
return nil, NewSyntaxError(p.tok.Pos, "Invalid field expression")
378378
}
379379
if len(fields) > 0 {
380+
if p.tok == nil {
381+
return nil, NewSyntaxError(-1, "Invalid field expression")
382+
}
380383
return nil, NewSyntaxError(p.tok.Pos, "Invalid field expression")
381384
}
382385
break
@@ -389,7 +392,9 @@ func (p *Parser) parseSelect() (*SelectStmt, error) {
389392
if p.tok != nil {
390393
if p.tok.Tp == AS {
391394
p.next()
392-
if p.tok.Tp != NAME {
395+
if p.tok == nil {
396+
return nil, NewSyntaxError(-1, "Require field name")
397+
} else if p.tok.Tp != NAME {
393398
return nil, NewSyntaxError(p.tok.Pos, "Invalid field name")
394399
}
395400
fieldName = p.tok.Data
@@ -644,10 +649,12 @@ func (p *Parser) parseOrderBy(selStmt *SelectStmt) (*OrderStmt, error) {
644649

645650
func (p *Parser) Parse() (*SelectStmt, error) {
646651
if p.numToks == 0 {
647-
return nil, NewSyntaxError(p.tok.Pos, "Expect select or where keyword")
652+
return nil, NewSyntaxError(-1, "Expect select or where keyword")
648653
}
649654
p.next()
650-
if p.tok == nil || (p.tok.Tp != WHERE && p.tok.Tp != SELECT) {
655+
if p.tok == nil {
656+
return nil, NewSyntaxError(-1, "Expect select or where keyword")
657+
} else if p.tok.Tp != WHERE && p.tok.Tp != SELECT {
651658
return nil, NewSyntaxError(p.tok.Pos, "Expect select or where keyword")
652659
}
653660
var (

query/parser_fuzz_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package query
2+
3+
import "testing"
4+
5+
func FuzzSQLParser(f *testing.F) {
6+
tests := []string{
7+
"select key, int(value) where int(key) + 1 >= 1 & (int(value) - 1 > 10 | int(value) <= 20)",
8+
"select key, int(value) where key ^= 'key' order by key limit 20, 10",
9+
"select * where key in ('k1', 'k2', 'k3')",
10+
"select * where (key between 'k1' and 'k3') & int(value) between 1 and 10",
11+
"select key, json(value)['test'] where key ^= 'k' & json(value)['test'][1] = 'v1'",
12+
}
13+
14+
for _, t := range tests {
15+
f.Add(t)
16+
}
17+
f.Fuzz(func(t *testing.T, query string) {
18+
o := NewOptimizer(query)
19+
o.buildPlan(nil)
20+
})
21+
}

0 commit comments

Comments
 (0)