mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-06 07:38:24 +00:00
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:
committed by
narimiran
parent
7b8ef1a901
commit
5eb96d40ee
@@ -15,6 +15,9 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
|
||||
val.add(how[i])
|
||||
i += 1
|
||||
else:
|
||||
if i + 1 >= how.len:
|
||||
raise newException(ValueError, "Syntax error in format string at " & $i)
|
||||
|
||||
if how[i + 1] == '$':
|
||||
val.add('$')
|
||||
i += 2
|
||||
@@ -27,7 +30,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
|
||||
i += 1
|
||||
var id {.inject.} = 0
|
||||
while i < how.len and how[i] in {'0'..'9'}:
|
||||
id += (id * 10) + (ord(how[i]) - ord('0'))
|
||||
id = (id * 10) + (ord(how[i]) - ord('0'))
|
||||
i += 1
|
||||
val.add(idgetter)
|
||||
lastNum = id + 1
|
||||
@@ -44,6 +47,8 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
|
||||
while i < how.len and how[i] != '}':
|
||||
name.add(how[i])
|
||||
i += 1
|
||||
if i >= how.len or how[i] != '}':
|
||||
raise newException(ValueError, "Syntax error in format string at " & $i)
|
||||
i += 1
|
||||
val.add(namegetter)
|
||||
else:
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user