aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/sqlvm/parser/parser.go
diff options
context:
space:
mode:
authorTing-Wei Lan <tingwei.lan@cobinhood.com>2019-03-04 16:06:14 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-05-06 10:44:04 +0800
commit126145a7eca2c054367abc65291ab1c90c51b998 (patch)
tree549ad2d5eb4c70f096d265cc3a7a6a9f1bb3c120 /core/vm/sqlvm/parser/parser.go
parentefabc336cf705aab463d81dd20e8d95df97e0965 (diff)
downloaddexon-126145a7eca2c054367abc65291ab1c90c51b998.tar
dexon-126145a7eca2c054367abc65291ab1c90c51b998.tar.gz
dexon-126145a7eca2c054367abc65291ab1c90c51b998.tar.bz2
dexon-126145a7eca2c054367abc65291ab1c90c51b998.tar.lz
dexon-126145a7eca2c054367abc65291ab1c90c51b998.tar.xz
dexon-126145a7eca2c054367abc65291ab1c90c51b998.tar.zst
dexon-126145a7eca2c054367abc65291ab1c90c51b998.zip
core: vm: sqlvm: limit the depth of AST to 1024
Since we traverse an AST by calling functions recursively, we have to protect the parser by limiting the depth of an AST.
Diffstat (limited to 'core/vm/sqlvm/parser/parser.go')
-rw-r--r--core/vm/sqlvm/parser/parser.go48
1 files changed, 41 insertions, 7 deletions
diff --git a/core/vm/sqlvm/parser/parser.go b/core/vm/sqlvm/parser/parser.go
index a90fec71c..8ed94e7aa 100644
--- a/core/vm/sqlvm/parser/parser.go
+++ b/core/vm/sqlvm/parser/parser.go
@@ -9,20 +9,40 @@ import (
"github.com/dexon-foundation/dexon/core/vm/sqlvm/parser/internal"
)
-func walkSelfFirst(n ast.Node, v func(ast.Node, []ast.Node)) {
+type visitor func(ast.Node, []ast.Node)
+
+func walkSelfFirst(n ast.Node, v visitor) bool {
+ return walkSelfFirstWithDepth(n, v, 0)
+}
+
+func walkSelfFirstWithDepth(n ast.Node, v visitor, d int) bool {
+ if d >= ast.DepthLimit {
+ return false
+ }
c := n.GetChildren()
+ r := true
v(n, c)
for i := range c {
- walkSelfFirst(c[i], v)
+ r = r && walkSelfFirstWithDepth(c[i], v, d+1)
}
+ return r
}
-func walkChildrenFirst(n ast.Node, v func(ast.Node, []ast.Node)) {
+func walkChildrenFirst(n ast.Node, v visitor) bool {
+ return walkChildrenFirstWithDepth(n, v, 0)
+}
+
+func walkChildrenFirstWithDepth(n ast.Node, v visitor, d int) bool {
+ if d >= ast.DepthLimit {
+ return false
+ }
c := n.GetChildren()
+ r := true
for i := range c {
- walkChildrenFirst(c[i], v)
+ r = r && walkChildrenFirstWithDepth(c[i], v, d+1)
}
v(n, c)
+ return r
}
// Parse parses SQL commands text and return an AST.
@@ -65,7 +85,8 @@ func Parse(b []byte) ([]ast.Node, error) {
if stmts[i] == nil {
continue
}
- walkChildrenFirst(stmts[i], func(n ast.Node, c []ast.Node) {
+ r := true
+ r = r && walkChildrenFirst(stmts[i], func(n ast.Node, c []ast.Node) {
minBegin := uint32(len(eb))
maxEnd := uint32(0)
for _, cn := range append(c, n) {
@@ -83,7 +104,7 @@ func Parse(b []byte) ([]ast.Node, error) {
n.SetPosition(minBegin)
n.SetLength(maxEnd - minBegin)
})
- walkSelfFirst(stmts[i], func(n ast.Node, _ []ast.Node) {
+ r = r && walkSelfFirst(stmts[i], func(n ast.Node, _ []ast.Node) {
begin := n.GetPosition()
end := begin + n.GetLength()
fixedBegin, ok := encMap[begin]
@@ -97,9 +118,22 @@ func Parse(b []byte) ([]ast.Node, error) {
n.SetPosition(fixedBegin)
n.SetLength(fixedEnd - fixedBegin)
})
+ if !r {
+ return nil, errors.ErrorList{
+ errors.Error{
+ Position: 0,
+ Category: errors.ErrorCategoryLimit,
+ Code: errors.ErrorCodeDepthLimitReached,
+ Token: "",
+ Prefix: "",
+ Message: fmt.Sprintf("reach syntax tree depth limit %d",
+ ast.DepthLimit),
+ },
+ }
+ }
}
if pigeonErr == nil {
- return stmts, pigeonErr
+ return stmts, nil
}
// Process errors.