nre: fix replacement string parser OOB access, numeric refs, and unterminated named refs (#25560)

1. A trailing `$` at the end of a replacement string could read out of
bounds via `how[i + 1]`; this now raises `ValueError` instead.

2. Numeric capture parsing used `id += (id * 10) + digit` instead of `id
= (id * 10) + digit`, so multi-digit refs were parsed incorrectly (e.g.
`$12` resolved as capture 13 instead of 12).

4. Unterminated named replacement syntax (e.g. `${foo)` is now rejected
with ValueError instead of being accepted and parsed inconsistently.

Found and fixed by GPT 5.3 Codex.

(cherry picked from commit 9b2b286baf)
This commit is contained in:
Raka Hourianto
2026-02-28 09:39:16 +03:00
committed by narimiran
parent 7b8ef1a901
commit 5eb96d40ee
2 changed files with 12 additions and 1 deletions

View File

@@ -14,9 +14,15 @@ block: # replace
check("123".replace(re"(\d)(\d)", "$#$#") == "123")
check("123".replace(re"(?<foo>\d)(\d)", "$foo$#$#") == "1123")
check("123".replace(re"(?<foo>\d)(\d)", "${foo}$#$#") == "1123")
check("abcdefghijklm".replace(re"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)", "$12") == "l")
block: # replacing missing captures should throw instead of segfaulting
expect IndexDefect: discard "ab".replace(re"(a)|(b)", "$1$2")
expect IndexDefect: discard "b".replace(re"(a)?(b)", "$1$2")
expect KeyError: discard "b".replace(re"(a)?", "${foo}")
expect KeyError: discard "b".replace(re"(?<foo>a)?", "${foo}")
block: # malformed replacement syntax should throw instead of OOB crash
expect ValueError: discard "a".replace(re"a", "$")
expect ValueError: discard "a".replace(re"a", "x$")
expect ValueError: discard "a".replace(re"a", "${foo")