diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim index ed84207766..e252af80d8 100644 --- a/lib/impure/nre/private/util.nim +++ b/lib/impure/nre/private/util.nim @@ -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: diff --git a/tests/stdlib/nre/replace.nim b/tests/stdlib/nre/replace.nim index 5cf659f213..290892bc4e 100644 --- a/tests/stdlib/nre/replace.nim +++ b/tests/stdlib/nre/replace.nim @@ -14,9 +14,15 @@ block: # replace check("123".replace(re"(\d)(\d)", "$#$#") == "123") check("123".replace(re"(?\d)(\d)", "$foo$#$#") == "1123") check("123".replace(re"(?\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"(?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")