zig icon indicating copy to clipboard operation
zig copied to clipboard

Valgrind reports passing uninitialized memory to writev, @cImport()/usingnamespace related

Open ifreund opened this issue 1 year ago • 6 comments

Zig Version

0.11.0-dev.168+b2ffe113d

Steps to Reproduce and Observed Behavior

const c = struct {
    pub usingnamespace @cImport({
        @cInclude("stdlib.h");
    });
};

test {
    _ = c;
}

Better stack trace from 0.10.0 for some reason:

valgrind ~/projects/zig/stage3-debug/bin/zig test foo.zig -lc        
==16815== Memcheck, a memory error detector
==16815== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==16815== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==16815== Command: /home/ifreund/projects/zig/stage3-debug/bin/zig test foo.zig -lc
==16815== 
Semantic Analysis [296] usingnamespace_0... ==16815== Syscall param writev(vector[2]) points to uninitialised byte(s)
==16815==    at 0xBD962CD: __writev (writev.c:26)
==16815==    by 0xBD962CD: writev (writev.c:24)
==16815==    by 0x3959B97: os.writev (os.zig:1152)
==16815==    by 0x39FB4BB: fs.file.File.writev (fs/file.zig:1166)
==16815==    by 0x3826F3A: fs.file.File.writevAll (fs/file.zig:1181)
==16815==    by 0x382542B: Module.astGenFile (Module.zig:3920)
==16815==    by 0x3CCE2AD: Sema.zirCImport (Sema.zig:5064)
==16815==    by 0x3A069BC: Sema.analyzeBodyInner (Sema.zig:819)
==16815==    by 0x38549E2: Sema.analyzeBodyBreak (Sema.zig:721)
==16815==    by 0x3850DCF: Module.semaDecl (Module.zig:4633)
==16815==    by 0x36A79A8: Module.ensureDeclAnalyzed (Module.zig:4258)
==16815==    by 0x36A509E: Compilation.processOneJob (Compilation.zig:3133)
==16815==    by 0x358A21E: Compilation.performAllTheWork (Compilation.zig:3003)
==16815==  Address 0x1f5dfc02 is 2,786 bytes inside a block of size 57,128 alloc'd
==16815==    at 0xBA997B5: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16815==    by 0x3479E03: heap.rawCAlloc (heap.zig:197)
==16815==    by 0x39F7BF5: rawAlloc (mem/Allocator.zig:154)
==16815==    by 0x39F7BF5: mem.Allocator.allocAdvancedWithRetAddr__anon_108537 (mem/Allocator.zig:302)
==16815==    by 0x3825EF3: mem.Allocator.alloc__anon_92078 (mem/Allocator.zig:194)
==16815==    by 0x3824CD2: Module.astGenFile (Module.zig:3870)
==16815==    by 0x3CCE2AD: Sema.zirCImport (Sema.zig:5064)
==16815==    by 0x3A069BC: Sema.analyzeBodyInner (Sema.zig:819)
==16815==    by 0x38549E2: Sema.analyzeBodyBreak (Sema.zig:721)
==16815==    by 0x3850DCF: Module.semaDecl (Module.zig:4633)
==16815==    by 0x36A79A8: Module.ensureDeclAnalyzed (Module.zig:4258)
==16815==    by 0x36A509E: Compilation.processOneJob (Compilation.zig:3133)
==16815==    by 0x358A21E: Compilation.performAllTheWork (Compilation.zig:3003)
==16815== 
All 1 tests passed.
==16815== 
==16815== HEAP SUMMARY:
==16815==     in use at exit: 815,080 bytes in 2,018 blocks
==16815==   total heap usage: 6,685,119 allocs, 6,683,101 frees, 1,452,877,285 bytes allocated
==16815== 
==16815== LEAK SUMMARY:
==16815==    definitely lost: 168,330 bytes in 14 blocks
==16815==    indirectly lost: 175,349 bytes in 20 blocks
==16815==      possibly lost: 0 bytes in 0 blocks
==16815==    still reachable: 471,401 bytes in 1,984 blocks
==16815==         suppressed: 0 bytes in 0 blocks
==16815== Rerun with --leak-check=full to see details of leaked memory
==16815== 
==16815== Use --track-origins=yes to see where uninitialised values come from
==16815== For lists of detected and suppressed errors, rerun with: -s
==16815== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

master branch at the commit listed above:

valgrind ~/projects/zig/stage3-master-debug/bin/zig test foo.zig -lc
==16356== Memcheck, a memory error detector
==16356== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==16356== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==16356== Command: /home/ifreund/projects/zig/stage3-master-debug/bin/zig test foo.zig -lc
==16356== 
Semantic Analysis [296] usingnamespace_0... ==16356== Syscall param writev(vector[2]) points to uninitialised byte(s)
==16356==    at 0xBD772CD: __writev (writev.c:26)
==16356==    by 0xBD772CD: writev (writev.c:24)
==16356==    by 0x39475C7: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x39E7C5B: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x381846E: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3816968: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3CB186F: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x39F2EBC: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3845515: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3841963: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x369CCF8: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x369A406: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x358537E: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==  Address 0x1f839ee2 is 2,786 bytes inside a block of size 58,328 alloc'd
==16356==    at 0xBA7A7B5: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16356==    by 0x347BE83: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x39E4735: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3817443: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x38162B7: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3CB186F: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x39F2EBC: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3845515: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x3841963: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x369CCF8: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x369A406: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356==    by 0x358537E: ??? (in /home/ifreund/projects/zig/stage3-master-debug/bin/zig)
==16356== 
All 1 tests passed.
==16356== 
==16356== HEAP SUMMARY:
==16356==     in use at exit: 814,939 bytes in 2,015 blocks
==16356==   total heap usage: 6,695,989 allocs, 6,693,974 frees, 1,461,354,485 bytes allocated
==16356== 
==16356== LEAK SUMMARY:
==16356==    definitely lost: 168,189 bytes in 11 blocks
==16356==    indirectly lost: 175,349 bytes in 20 blocks
==16356==      possibly lost: 0 bytes in 0 blocks
==16356==    still reachable: 471,401 bytes in 1,984 blocks
==16356==         suppressed: 0 bytes in 0 blocks
==16356== Rerun with --leak-check=full to see details of leaked memory
==16356== 
==16356== Use --track-origins=yes to see where uninitialised values come from
==16356== For lists of detected and suppressed errors, rerun with: -s
==16356== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Expected Behavior

No uninitialized memory should be passed to the kernel, nothing good can come of it.

ifreund avatar Nov 13 '22 17:11 ifreund

As per #12676 I've tagged this with miscompilation and added it to the 0.10.1 milestone to be on the safe side.

ifreund avatar Nov 13 '22 17:11 ifreund

I have previously noticed that the Zir files stored in the cache are non-deterministic, and this looks like a potential cause of that issue, but I didn't bother looking any closer since it didn't affect the linker outputs.

I would venture to guess that it's writing undefined padding to the file, which would never be looked at when the file is read back in, but valgrind has no way of knowing that. Deterministic Zir files would definitely be useful regardless.

jacobly0 avatar Nov 13 '22 17:11 jacobly0

~~This looks like the cause: https://github.com/ziglang/zig/blob/684264908e50bc8537fc10859e93ccdf8d94509e/src/Module.zig#L3868-L3872~~

I don't get the error in the issue but it is saying that data_ptr is pointing to uninitialized byte(s):

==51599== Syscall param writev(vector[...]) points to uninitialised byte(s)
...
==51599==  Address 0x16525452 is 2,786 bytes inside a block of size 62,080 alloc'd

Vexu avatar Nov 16 '22 13:11 Vexu

I dont get any error: zig test valgrind.zig -lc --test-no-exec. valgrind -s zig-cache/o/21cf3ed8f95b0445e844c831bdd50e85/test. Or better with zig test valgrind.zig -lc --test-cmd valgrind --test-cmd '-s' --test-cmd-bin:

zig test valgrind.zig -lc --test-cmd valgrind --test-cmd '-s' --test-cmd-bin
==726754== Memcheck, a memory error detector
==726754== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==726754== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==726754== Command: /home/misterspoon/dev/git/zi/zig/enable_parsefloat/zig-cache/o/21cf3ed8f95b0445e844c831bdd50e8
5/test
==726754== 
All 1 tests passed.
==726754== 
==726754== HEAP SUMMARY:
==726754==     in use at exit: 0 bytes in 0 blocks
==726754==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==726754== 
==726754== All heap blocks were freed -- no leaks are possible
==726754== 
==726754== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Suggestion to close or please provide host information on which architecture this fails.

matu3ba avatar Jul 24 '23 22:07 matu3ba

Suggestion to close or please provide host information on which architecture this fails.

I originally hit this on x86_64 glibc based linux. I haven't tried to reproduce it since reporting this issue though.

ifreund avatar Jul 25 '23 08:07 ifreund

Issue still present in version 0.12.0-dev.3405+31791ae15. Can be reproduced by running the behavior tests in Valgrind.

andrewrk avatar Mar 21 '24 21:03 andrewrk