Skip to content

Commit

Permalink
Don't crash for invalid toplevel parseStmt/Expr calls (nim-lang#23089)
Browse files Browse the repository at this point in the history
This code will crash `check`/`nimsuggest` since the `ra` register is
uninitialised

```nim
import macros

static:
  discard parseExpr("'")
```
Now it assigns an empty node so that it has something

Testament changes were so I could properly write a test. It would pass
even with a segfault since it could find the error
  • Loading branch information
ire4ever1190 authored Dec 19, 2023
1 parent 6618448 commit db9d800
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
3 changes: 3 additions & 0 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
if error.len == 0 and msg <= errMax:
error = formatMsg(conf, info, msg, arg))

regs[ra].node = newNode(nkEmpty)
if error.len > 0:
c.errorFlag = error
elif ast.len != 1:
Expand All @@ -1942,6 +1944,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
error = formatMsg(conf, info, msg, arg))
if error.len > 0:
c.errorFlag = error
regs[ra].node = newNode(nkEmpty)
else:
regs[ra].node = ast
of opcQueryErrorFlag:
Expand Down
13 changes: 9 additions & 4 deletions testament/testament.nim
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,16 @@ proc callNimCompiler(cmdTemplate, filename, options, nimcache: string,
foundSuccessMsg = true
elif not running(p):
break
close(p)
result.msg = ""
result.file = ""
result.output = ""
result.line = 0
result.column = 0

result.err = reNimcCrash
let exitCode = p.peekExitCode
case exitCode
result.exitCode = p.peekExitCode
close p
case result.exitCode
of 0:
if foundErrorMsg:
result.debugInfo.add " compiler exit code was 0 but some Error's were found."
Expand All @@ -214,7 +214,7 @@ proc callNimCompiler(cmdTemplate, filename, options, nimcache: string,
if foundSuccessMsg:
result.debugInfo.add " compiler exit code was 1 but no `isSuccess` was true."
else:
result.debugInfo.add " expected compiler exit code 0 or 1, got $1." % $exitCode
result.debugInfo.add " expected compiler exit code 0 or 1, got $1." % $result.exitCode

if err =~ pegLineError:
result.file = extractFilename(matches[0])
Expand Down Expand Up @@ -521,7 +521,12 @@ proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
r.addResult(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
compilerOutputTests(test, target, extraOptions, given, expected, r)
of actionReject:
# Make sure its the compiler rejecting and not the system (e.g. segfault)
cmpMsgs(r, expected, given, test, target, extraOptions)
if given.exitCode != QuitFailure:
r.addResult(test, target, extraOptions, "exitcode: " & $QuitFailure,
"exitcode: " & $given.exitCode & "\n\nOutput:\n" &
given.nimout, reExitcodesDiffer)

proc targetHelper(r: var TResults, test: TTest, expected: TSpec, extraOptions: string) =
for target in expected.targets:
Expand Down
15 changes: 15 additions & 0 deletions tests/macros/tfail_parse.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
discard """
action: "reject"
cmd: "nim check $file"
errormsg: "expected expression, but got multiple statements [ValueError]"
file: "macros.nim"
"""

import macros
static:
discard parseStmt("'")
discard parseExpr("'")
discard parseExpr("""
proc foo()
proc foo() = discard
""")

0 comments on commit db9d800

Please sign in to comment.