aboutsummaryrefslogtreecommitdiff
path: root/src/text/template/parse/parse.go
diff options
context:
space:
mode:
authorVille Vesilehto <ville@vesilehto.fi>2025-05-14 18:16:54 +0000
committerGopher Robot <gobot@golang.org>2025-05-17 03:27:48 -0700
commit42f9ee904caf6681ee32e7b048f15ab7cddf3eb3 (patch)
treedba6ef2dd28748581ba950cea159801160154797 /src/text/template/parse/parse.go
parent6425749695130f2032ac9cfdf5407b6a322534db (diff)
downloadgo-42f9ee904caf6681ee32e7b048f15ab7cddf3eb3.tar.xz
text/template: limit expression parenthesis nesting
Deeply nested parenthesized expressions could cause a stack overflow during parsing. This change introduces a depth limit (maxStackDepth) tracked in Tree.stackDepth to prevent this. Additionally, this commit clarifies the security model in the package documentation, noting that template authors are trusted as text/template does not auto-escape. Fixes #71201 Change-Id: Iab2c2ea6c193ceb44bb2bc7554f3fccf99a9542f GitHub-Last-Rev: f4ebd1719ff966ae3c6516e3fb935dfea2f5362e GitHub-Pull-Request: golang/go#73670 Reviewed-on: https://go-review.googlesource.com/c/go/+/671755 Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Auto-Submit: Sean Liao <sean@liao.dev> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Rob Pike <r@golang.org>
Diffstat (limited to 'src/text/template/parse/parse.go')
-rw-r--r--src/text/template/parse/parse.go18
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)