feat: add stack guard pages so overflow faults instead of corrupting memory - #7
Merged
Conversation
New src/stack.zig maps a fiber stack with one no-access guard page immediately below the usable region, so a stack overflow faults instead of silently corrupting memory. Linux uses mmap + a raw mprotect syscall; Windows reserves the whole region and commits only the usable part, leaving the guard page reserved-but-uncommitted (any access faults). Supported on Linux and Windows; compileError elsewhere.
create now allocates the stack via src/stack.zig (guard-paged) instead of the passed allocator, which now backs only the Fiber struct; destroy frees it via stack.zig. Revise the OOM test (the stack no longer uses the allocator, so only the struct allocation can fail) and re-export min_stack_size from root.
Add a standalone overflow-probe exe that overflows a guarded fiber, and a test that spawns it and asserts abnormal termination (a signal on POSIX, a non-zero exit on Windows). The probe is fail-closed: any non-fault outcome exits 0, which the test treats as failure, so a setup error cannot masquerade as a guard fault. build.zig installs the probe and passes its path via FIBER_OVERFLOW_PROBE.
Consume the per-frame buffer after the recursive call so the frame must outlive it, provably defeating tail-call optimization. Otherwise an optimized build could turn the overflow recursion into a non-growing loop and the guard page would never fault, silently invalidating the proof.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Give every fiber stack a no-access guard page below it, so a stack overflow faults cleanly (SIGSEGV / access violation) at the point of overflow instead of silently corrupting adjacent memory. (Phase C sub-project C3 — the robustness centerpiece.)
Changes
src/stack.zig— a guard-paged stack allocator. Linux:mmapthe region read/write, then a rawmprotectturns the low page into a no-access guard;munmapfrees it. Windows:NtAllocateVirtualMemoryreserves the whole region and commits only the usable part, leaving the low guard page reserved-but-uncommitted (any access → access violation);NtFreeVirtualMemoryreleases it.@compileErroron other targets — guard-paged stacks are x86_64 Linux/Windows only.create/destroynow allocate/free the stack viastack.zig; the passed allocator backs only the smallFiberstruct.resetis unchanged.min_stack_sizeis re-exported fromroot.zig.overflow-probeexe overflows a guarded fiber; a test spawns it and asserts abnormal termination. The probe is fail-closed (any non-fault outcome exits 0, which the test treats as failure), so a setup error can never masquerade as a guard fault.Notes
The stack no longer uses the passed allocator, so the OOM test was reduced to the struct-allocation case.
Fiber.stack.lenis now page-rounded (≥ the requestedstack_size). The Windows guard fault is verified locally; the Linuxmmap/mprotectruntime and Linux guard fault are proven only by CI (ubuntu-latest).Test Plan
zig build testpasses across all four optimize modes locally (Windows), including the guard-fault test (the probe genuinely crashes on the guard page)zig build examples,zig fmt --check .pass