diff options
Diffstat (limited to 'src/text/template/parse/parse.go')
| -rw-r--r-- | src/text/template/parse/parse.go | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go index 27c84f31eb..84d639d78d 100644 --- a/src/text/template/parse/parse.go +++ b/src/text/template/parse/parse.go @@ -32,6 +32,7 @@ type Tree struct { treeSet map[string]*Tree actionLine int // line of left delim starting action rangeDepth int + stackDepth int // depth of nested parenthesized expressions } // A mode value is a set of flags (or 0). Modes control parser behavior. @@ -42,6 +43,17 @@ const ( SkipFuncCheck // do not check that functions are defined ) +// maxStackDepth is the maximum depth permitted for nested +// parenthesized expressions. +var maxStackDepth = 10000 + +// init reduces maxStackDepth for WebAssembly due to its smaller stack size. +func init() { + if runtime.GOARCH == "wasm" { + maxStackDepth = 1000 + } +} + // Copy returns a copy of the [Tree]. Any parsing state is discarded. func (t *Tree) Copy() *Tree { if t == nil { @@ -223,6 +235,7 @@ func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string t.vars = []string{"$"} t.funcs = funcs t.treeSet = treeSet + t.stackDepth = 0 lex.options = lexOptions{ emitComment: t.Mode&ParseComments != 0, breakOK: !t.hasFunction("break"), @@ -787,6 +800,11 @@ func (t *Tree) term() Node { } return number case itemLeftParen: + if t.stackDepth >= maxStackDepth { + t.errorf("max expression depth exceeded") + } + t.stackDepth++ + defer func() { t.stackDepth-- }() return t.pipeline("parenthesized pipeline", itemRightParen) case itemString, itemRawString: s, err := strconv.Unquote(token.val) |
