Nim
Nim copied to clipboard
UB calling `allocCStringArray([""])` with `--mm:refc`
Description
discard allocCStringArray([""])
compiled with
nim c -r --mm:refc --passC="-fsanitize=undefined" --passL="-fsanitize=undefined" a.nim
Where allocCStringArray compiles to:
N_LIB_PRIVATE N_NIMCALL(NCSTRING*, allocCStringArray__system_u2460)(NimStringDesc** a_p0, NI a_p0Len_0) {
NCSTRING* result;
void* T1_;
NimStringDesc** x;
result = (NCSTRING*)0;
T1_ = (void*)0;
T1_ = alloc0Impl__system_u1800(((NI) ((NI)((NI)(a_p0Len_0 + ((NI)1)) * ((NI)8)))));
result = ((NCSTRING*) (T1_));
x = ((NimStringDesc**) (a_p0));
{
NI i;
NI colontmp_;
NI res;
i = (NI)0;
colontmp_ = (NI)0;
colontmp_ = (a_p0Len_0-1);
res = ((NI)0);
{
while (1) {
void* T5_;
if (!(res <= colontmp_)) goto LA4;
i = res;
T5_ = (void*)0;
T5_ = alloc0Impl__system_u1800(((NI) ((NI)((x[i] ? x[i]->Sup.len : 0) + ((NI)1)))));
result[i] = ((NCSTRING) (T5_));
copyMem__system_u1782(((void*) (result[i])), ((void*) ((&x[i]->data[((NI)0)]))), ((NI) ((x[i] ? x[i]->Sup.len : 0))));
res += ((NI)1);
} LA4: ;
}
}
return result;
}
...
static NIM_CONST tyArray__nHXaesL0DJZHyVS07ARPRA TM__R8RUzYq41iOx0I9bZH5Nyrw_2 = {((NimStringDesc*) NIM_NIL)}
;
...
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
NCSTRING* T1_;
T1_ = (NCSTRING*)0;
T1_ = allocCStringArray__system_u2460(TM__R8RUzYq41iOx0I9bZH5Nyrw_2, 1);
(void)(T1_);
popFrame();
}
}
and the current output occurs on
copyMem__system_u1782(((void*) (result[i])), ((void*) ((&x[i]->data[((NI)0)]))), ((NI) ((x[i] ? x[i]->Sup.len : 0))));
because ((void*) ((&x[i]->data[((NI)0)]))) is, as usual for this sort of offsetof approach, undefined behavior when x[i] == NULL, as is the case with the empty string here.
Nim Version
Nim Compiler Version 1.9.5 [Linux: amd64]
Compiled at 2023-06-25
Copyright (c) 2006-2023 by Andreas Rumpf
git hash: f718f295df3f6ee5d7fd6fc19e39ac663821b00a
active boot switches: -d:release
gcc (Debian 12.3.0-4) 12.3.0
Copyright (C) 2022 Free Software Foundation, Inc.
Debian clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Current Output
.cache/nim/a_d/@mNim@[email protected]:5983:61: runtime error: member access within null pointer of type 'struct NimStringDesc'
Expected Output
No undefined behavior detected by UBSAN
Possible Solution
No response
Additional Information
No response
As I wrote elsewhere, these sanitizer rules are broken, against the spirit of C and against how address computations work on every CPU ever invented.