ast: fuzzed parser bug, two codeql issues (#3988)

* storage/path.Ref: parse int64 into ast.Number
* ast/PtrRef: guard against giant paths

I don't believe this limit is every going to be reached. But CodeQL had flagged
this, and it's not entirely wrong. Let's error our on giant wonky inputs instead
of seeing what'll happen with it eventually.

* ast/parser: fix bad import alias var

The fuzzer came up with that!

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
This commit is contained in:
Stephan Renatus
2021-11-08 14:10:32 +01:00
committed by GitHub
parent fb301d2713
commit c99b645194
5 changed files with 17 additions and 9 deletions
+8 -7
View File
@@ -472,14 +472,15 @@ func (p *Parser) parseImport() *Import {
return nil
}
alias := p.parseTerm()
v, ok := alias.Value.(Var)
if !ok {
p.illegal("expected var")
return nil
if alias := p.parseTerm(); alias != nil {
v, ok := alias.Value.(Var)
if ok {
imp.Alias = v
return &imp
}
}
imp.Alias = v
p.illegal("expected var")
return nil
}
return &imp
+1
View File
@@ -1091,6 +1091,7 @@ func TestImport(t *testing.T) {
assertParseErrorContains(t, "non-ground ref", "import data.foo[x]", "rego_parse_error: unexpected var token: expecting string")
assertParseErrorContains(t, "non-string", "import input.foo[0]", "rego_parse_error: unexpected number token: expecting string")
assertParseErrorContains(t, "unknown root", "import foo.bar", "rego_parse_error: unexpected import path, must begin with one of: {data, future, input}, got: foo")
assertParseErrorContains(t, "bad variable term", "import input as A(", "rego_parse_error: unexpected eof token: expected var")
_, _, err := ParseStatements("", "package foo\nimport bar.data\ndefault foo=1")
if err == nil {
+4
View File
@@ -10,6 +10,7 @@ import (
"encoding/json"
"fmt"
"io"
"math"
"math/big"
"net/url"
"regexp"
@@ -843,6 +844,9 @@ func PtrRef(head *Term, s string) (Ref, error) {
return Ref{head}, nil
}
parts := strings.Split(s, "/")
if max := math.MaxInt32; len(parts) >= max {
return nil, fmt.Errorf("path too long: %s, %d > %d (max)", s, len(parts), max)
}
ref := make(Ref, uint(len(parts))+1)
ref[0] = head
for i := 0; i < len(parts); i++ {
+2 -2
View File
@@ -125,9 +125,9 @@ func (p Path) Ref(head *ast.Term) (ref ast.Ref) {
ref = make(ast.Ref, len(p)+1)
ref[0] = head
for i := range p {
idx, err := strconv.ParseInt(p[i], 10, 32)
idx, err := strconv.ParseInt(p[i], 10, 64)
if err == nil {
ref[i+1] = ast.IntNumberTerm(int(idx))
ref[i+1] = ast.UIntNumberTerm(uint64(idx))
} else {
ref[i+1] = ast.StringTerm(p[i])
}
+2
View File
@@ -5,6 +5,7 @@
package storage
import (
"math"
"reflect"
"testing"
@@ -179,6 +180,7 @@ func TestPathRef(t *testing.T) {
{"/", "data", "data"},
{"/foo/bar", "data", "data.foo.bar"},
{"/foo/bar/3", "data", "data.foo.bar[3]"},
{fmt.Sprintf("/foo/bar/%d", math.MaxInt64), "data", fmt.Sprintf("data.foo.bar[%d]", math.MaxInt64)},
}
for _, tc := range tests {
path := MustParsePath(tc.path)