-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Description
- Nim version: v2.0.2, arm64-native version
- OS: MacOS Sonoma 14.2.1
Inside proc [][Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T
, codegen contains an unitialized variable. In the middle of signaling a range error, the caller crashes before the traceback can be fully printed by dereferencing the uninitialized result.
Here's a minimal example:
proc foo() =
for _ in @[1, 3, 5]:
discard "abcde"[25..<10]
break
echo "Passed"
when isMainModule:
foo()
Nim Version
$ nim --version
Nim Compiler Version 2.0.2 [MacOSX: arm64]
Compiled at 2023-12-15
Copyright (c) 2006-2023 by Andreas Rumpf
active boot switches: -d:release -d:nimUseLinenoise
Current Output
$ nim c test
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.2/nim/config/nim.cfg' [Conf]
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.2/nim/config/config.nims' [Conf]
......................................................................
Hint: [Link]
Hint: mm: orc; threads: on; opt: none (DEBUG BUILD, `-d:release` generates faster code)
27618 lines; 0.178s; 30.352MiB peakmem; proj: /private/tmp/stuff/test; out: /private/tmp/stuff/test [SuccessX]
$ file test
test: Mach-O 64-bit executable arm64
$ ./test
Traceback (most recent call last)
/private/tmp/stuff/test.nim(8) test
/opt/homebrew/Cellar/nim/2.0.2/nim/lib/system.nim(370) foo
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
fish: Job 1, './test' terminated by signal SIGSEGV (Address boundary error)
Expected Output
Should throw an unhandled exception, not SIGSEGV:
/private/tmp/stuff/test.nim(8) test
/private/tmp/stuff/test.nim(2) foo
/opt/homebrew/Cellar/nim/2.0.2/nim/lib/system/indices.nim(85) []
/opt/homebrew/Cellar/nim/2.0.2/nim/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: value out of range: -15 notin 0 .. 9223372036854775807 [RangeDefect]
Error: execution of an external program failed: '/Users/kimmy/.cache/nim/test_d/test_FFA6C1D31EF4FF0BF49E574367D1CFEF1CB99BEC'
Possible Solution
See my comment below about break
.
Additional Information
Watching the crash from the debugger's view, we have:
$ nim c -c --nimcache:. test; cc -g *.c; lldb ./a.out
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.2/nim/config/nim.cfg' [Conf]
Hint: used config file '/opt/homebrew/Cellar/nim/2.0.2/nim/config/config.nims' [Conf]
......................................................................
Hint: mm: orc; threads: on; opt: none (DEBUG BUILD, `-d:release` generates faster code)
27618 lines; 0.116s; 30.352MiB peakmem; proj: /private/tmp/stuff/test; out: /private/tmp/stuff/test.json [SuccessX]
(lldb) target create "./a.out"
Current executable set to '/private/tmp/stuff/a.out' (arm64).
(lldb) r
Process 67319 launched: '/private/tmp/stuff/a.out' (arm64)
Process 67319 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x9)
frame #0: 0x000000010000e834 a.out`foo__test_u1 at @mtest.nim.c:285:112
282 LA6_:;
283 }
284 {
-> 285 nimlf_(370, "/opt/homebrew/Cellar/nim/2.0.2/nim/lib/system.nim"); if (colontmpD_.p && !(colontmpD_.p->cap & NIM_STRLIT_FLAG)) {
286 deallocShared(colontmpD_.p);
287 }
288 }
Target 0: (a.out) stopped.
At this point, colontmpD_
happens to contain the last thing in stack. Looks like some earlier slice object:
(lldb) p colontmpD_
(NimStringV2) {
len = 25
p = 0x0000000000000009
}
(lldb)
colontmpD_
originates from the codegen for proc [][Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T
, called earlier. Ultimately, NimStringV2 result;
is unitialized before the function returns prematurely to signal the range error:
static N_INLINE(NimStringV2, X5BX5D___test_u93)(NimStringV2 s_p0, tyObject_HSlice__ZWg9b9a9br09cvqTdM59aM3bQ9bw x_p1) {
NimStringV2 result;
NI a;
NI L;
NI TM__ipcYmBC9bj9a1BW35ABoB1Kw_2;
NI TM__ipcYmBC9bj9a1BW35ABoB1Kw_3;
nimfr_("[]", "/opt/homebrew/Cellar/nim/2.0.2/nim/lib/system/indices.nim");
{ nimln_(83); a = x_p1.a;
nimln_(84); if (nimSubInt(x_p1.b, a, &TM__ipcYmBC9bj9a1BW35ABoB1Kw_2)) { raiseOverflow(); goto BeforeRet_;
};
if (nimAddInt((NI)(TM__ipcYmBC9bj9a1BW35ABoB1Kw_2), ((NI)1), &TM__ipcYmBC9bj9a1BW35ABoB1Kw_3)) { raiseOverflow(); goto BeforeRet_;
};
L = (NI)(TM__ipcYmBC9bj9a1BW35ABoB1Kw_3);
nimln_(85); if ((L) < ((NI)0) || (L) > ((NI)IL64(9223372036854775807))){ raiseRangeErrorI(L, ((NI)0), ((NI)IL64(9223372036854775807))); goto BeforeRet_;
}
// ^ control exits here... result.p is 0x000000009 on my system