Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stack_probe.zig causing segmentation fault in Debug Mode #17195

Closed
VisenDev opened this issue Sep 18, 2023 · 8 comments
Closed

stack_probe.zig causing segmentation fault in Debug Mode #17195

VisenDev opened this issue Sep 18, 2023 · 8 comments

Comments

@VisenDev
Copy link

VisenDev commented Sep 18, 2023

Zig Version

0.11.0

Steps to Reproduce and Observed Behavior

stack_probe.zig is causing a segmentation fault when in debug mode. Here is one instance where this happened

This stack segmentation fault is also happening when attempting to parse large json strings using std.json.parseFromSlice

Example code causing a segfault. level.Level is a large struct.

    const string = try std.fs.cwd().readFileAlloc(a, path, 100000);
    if (!try std.json.validate(a, string)) {
        return error.invalid_json;
    }
    const parsed = try std.json.parseFromSlice(level.Level, a, string, .{});
Process 13483 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ff7bf6ff500)
    frame #0: 0x0000000100164c54 dev`__zig_probe_stack at stack_probe.zig:53:13 [opt]
   50  	    switch (arch) {
   51  	        .x86_64 => {
   52  	            // %rax = probe length, %rsp = stack pointer
-> 53  	            asm volatile (
   54  	                \\        push   %%rcx
   55  	                \\        mov    %%rax, %%rcx
   56  	                \\        cmp    $0x1000,%%rcx
warning: dev was compiled with optimization - stepping may behave oddly; variables may not be available.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ff7bf6ff500)
  * frame #0: 0x0000000100164c54 dev`__zig_probe_stack at stack_probe.zig:53:13 [opt]
    frame #1: 0x00000001000a0f89 dev`json.static.innerParse__anon_16225(allocator=mem.Allocator @ 0x00007ff7bfc75588, source=0x00007ff7bfd02868, options=json.static.ParseOptions @ 0x00007ff7bfbe8260) at static.zig:361:63
    frame #2: 0x0000000100088e4e dev`json.static.innerParse__anon_15817(allocator=mem.Allocator @ 0x00007ff7bfc75588, source=0x00007ff7bfd02868, options=json.static.ParseOptions @ 0x00007ff7bfbe8260) at static.zig:361:63
    frame #3: 0x000000010006fbf0 dev`json.static.parseFromTokenSourceLeaky__anon_14537(allocator=mem.Allocator @ 0x00007ff7bfc75588, scanner_or_reader=0x00007ff7bfd02868, options=json.static.ParseOptions @ 0x00000001001d3980) at static.zig:140:33
    frame #4: 0x00000001000409c4 dev`json.static.parseFromTokenSource__anon_11798(allocator=mem.Allocator @ 0x00007ff7bfeff338, scanner_or_reader=0x00007ff7bfd02868, options=json.static.ParseOptions @ 0x00000001001d3980) at static.zig:107:49
    frame #5: 0x000000010002c19f dev`json.static.parseFromSlice__anon_10958(allocator=mem.Allocator @ 0x00007ff7bfeff338,

When the code is compiled in modes other than debug, the segmentation fault does not happen

Expected Behavior

No segmentation fault

@VisenDev VisenDev added the bug Observed behavior contradicts documented or intended behavior label Sep 18, 2023
@VisenDev
Copy link
Author

This could possibly be a duplicate of this issue

But that issue doesn't mention this section of the std lib causing a segmentation fault, so this might be a separate issue

@arnthorla
Copy link

@VisenDev
I'm hitting the same exact bug at the moment. Code segfaults at the same exact line in zig/compiler_rt/stack_probe.zig:53, while exploring the state space of the 8-puzzle game and storing the states using std.AutoHashMap(). Similar conditions, i.e. under high memory load. (Version 0.11.0)

@VisenDev
Copy link
Author

@arnthorla
From spending a lot of time investigating this issue, it seems to be caused by a stack overflow. The way to stop the segmentation fault is to try to allocate more memory on the heap, and avoid large stack allocated values.

For me, changing some fields in a struct to pointers to values instead of the values themselves seemed to fix the segmentation faults with json parsing, hope this can point you in the right direction

@arnthorla
Copy link

Thanks @VisenDev
On further thought, I think I just blew the stack limit because of recursion. I found the error message rather confusing though. But I have not gotten around to implement an iterative solution to confirm that suspicion yet.

@cdemirer
Copy link

@VisenDev What's the size of level.Level?

@cdemirer
Copy link

cdemirer commented Jul 1, 2024

I think I may have found the issue.

Repro:

const std = @import("std");

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const ally = gpa.allocator();

const Big = struct {
    array: [100_000_000]u8 = undefined,
};

const Small = struct {
    value: u8,
    big: *Big,
};

pub fn main() !void {
    _ = try std.json.parseFromSlice(Small, ally, "{ \"value\": 123, \"big\": {} }", .{});
}

Even though Small is small, and Small.big is allocated in heap during parsing, there are still statements in the code that cause a stack allocation of Big. For example this one:

r.* = try innerParse(ptrInfo.child, allocator, source, options);

This may possibly change when #8824 is implemented.


Do you think the issue described above might be the reason of your stack overflow too? If so, I suggest editing the title to refer to this instead of the part related to #7371.

@nektro
Copy link
Contributor

nektro commented Jul 1, 2024

maybe related #15685 #16343

@andrewrk
Copy link
Member

Duplicate of #7371

@andrewrk andrewrk marked this as a duplicate of #7371 Aug 13, 2024
@andrewrk andrewrk closed this as not planned Won't fix, can't repro, duplicate, stale Aug 13, 2024
@andrewrk andrewrk removed the bug Observed behavior contradicts documented or intended behavior label Aug 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants