diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2022-09-15 13:36:08 -0600 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2022-09-15 13:36:08 -0600 |
commit | 2dc747cf2d7dd4e7337c1d7665042b896f3b4445 (patch) | |
tree | cca5ae1f71737a52ff4716d86a5ca59ff9eb6b14 | |
parent | e338648fed3263200dfd6abc9f8100c6f1c0eb67 (diff) |
Limit unclosed placeholder tolerance (fix #4170)
-rw-r--r-- | replacer.go | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/replacer.go b/replacer.go index d30a406..5797920 100644 --- a/replacer.go +++ b/replacer.go @@ -144,9 +144,11 @@ func (r *Replacer) replace(input, empty string, // iterate the input to find each placeholder var lastWriteCursor int + // fail fast if too many placeholders are unclosed + var unclosedCount int + scan: for i := 0; i < len(input); i++ { - // check for escaped braces if i > 0 && input[i-1] == phEscape && (input[i] == phClose || input[i] == phOpen) { sb.WriteString(input[lastWriteCursor : i-1]) @@ -158,9 +160,17 @@ scan: continue } + // our iterator is now on an unescaped open brace (start of placeholder) + + // too many unclosed placeholders in absolutely ridiculous input can be extremely slow (issue #4170) + if unclosedCount > 100 { + return "", fmt.Errorf("too many unclosed placeholders") + } + // find the end of the placeholder end := strings.Index(input[i:], string(phClose)) + i if end < i { + unclosedCount++ continue } @@ -168,6 +178,7 @@ scan: for end > 0 && end < len(input)-1 && input[end-1] == phEscape { nextEnd := strings.Index(input[end+1:], string(phClose)) if nextEnd < 0 { + unclosedCount++ continue scan } end += nextEnd + 1 |