[feature] add arbitrary code execution to strformat (#17694)

* changed parser to ignore ':' within parens
* Update strformat.nim
* Update lib/pure/strformat.nim

Co-authored-by: flywind <xzsflywind@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
shirleyquirk
2021-04-11 12:07:23 +01:00
committed by GitHub
parent 3aaec0647b
commit a5b30c94c2

View File

@@ -74,6 +74,20 @@ runnableExamples:
assert fmt"{123.456:13e}" == " 1.234560e+02"
##[
# Expressions
]##
runnableExamples:
let x = 3.14
assert fmt"{(if x!=0: 1.0/x else: 0):.5}" == "0.31847"
assert fmt"""{(block:
var res: string
for i in 1..15:
res.add (if i mod 15 == 0: "FizzBuzz"
elif i mod 5 == 0: "Buzz"
elif i mod 3 == 0: "Fizz"
else: $i) & " "
res)}""" == "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz "
##[
# Debugging strings
`fmt"{expr=}"` expands to `fmt"expr={expr}"` namely the text of the expression,
@@ -557,7 +571,7 @@ proc strformatImpl(pattern: NimNode; openChar, closeChar: char): NimNode =
# XXX: https://github.com/nim-lang/Nim/issues/8405
# When compiling with -d:useNimRtl, certain procs such as `count` from the strutils
# module are not accessible at compile-time:
let expectedGrowth = when defined(useNimRtl): 0 else: count(f, '{') * 10
let expectedGrowth = when defined(useNimRtl): 0 else: count(f, openChar) * 10
result.add newVarStmt(res, newCall(bindSym"newStringOfCap",
newLit(f.len + expectedGrowth)))
var strlit = ""
@@ -573,8 +587,12 @@ proc strformatImpl(pattern: NimNode; openChar, closeChar: char): NimNode =
strlit = ""
var subexpr = ""
while i < f.len and f[i] != closeChar and f[i] != ':':
if f[i] == '=':
var inParens = 0
while i < f.len and f[i] != closeChar and (f[i] != ':' or inParens!=0):
case f[i]
of '(': inc inParens
of ')': dec inParens
of '=':
let start = i
inc i
i += f.skipWhitespace(i)
@@ -582,10 +600,11 @@ proc strformatImpl(pattern: NimNode; openChar, closeChar: char): NimNode =
result.add newCall(bindSym"add", res, newLit(subexpr & f[start ..< i]))
else:
subexpr.add f[start ..< i]
else:
subexpr.add f[i]
inc i
continue
else: discard
subexpr.add f[i]
inc i
var x: NimNode
try:
x = parseExpr(subexpr)
@@ -608,11 +627,11 @@ proc strformatImpl(pattern: NimNode; openChar, closeChar: char): NimNode =
doAssert false, "invalid format string: missing '}'"
result.add newCall(formatSym, res, x, newLit(options))
elif f[i] == closeChar:
if f[i+1] == closeChar:
if i<f.len-1 and f[i+1] == closeChar:
strlit.add closeChar
inc i, 2
else:
doAssert false, "invalid format string: '}' instead of '}}'"
doAssert false, "invalid format string: '$1' instead of '$1$1'" % $closeChar
inc i
else:
strlit.add f[i]