Source linked

Fil-C Tames setjmp/longjmp Without Sacrificing Memory Safety

Fil-C's new release 0.680 implements longjmp, setjmp, and ucontext APIs with zero dangling stack exploits - turning the dirtiest corner of C into a safe operation.

fil cmemory safetysetjmplongjmpucontextc programming

Fil-C release 0.680 ships the first memory-safe implementation of setjmp, longjmp, and the full ucontext API (getcontext, setcontext, makecontext, swapcontext). Anyone who's debugged a corrupted stack after a misplaced longjmp knows why this matters: the old approach let you silently resume execution on a freed stack, turning subtle bugs into exploitable vulnerabilities. Fil-C makes that impossible.

Why setjmp Is Fundamentally Evil

setjmp returns twice. On the first call it saves the caller's context, returns 0; later longjmp restores that context and setjmp returns again with a non-zero value. The compiler is free to optimize variables across that boundary — spilling them to different stack slots, folding constants, or reusing slots whose liveness it doesn't understand. The standard workaround is volatile, but that's a bandage.

Consider the canonical example: you save a context, modify a local, then longjmp back. Without volatile, the compiler may constant-fold the variable or give it separate spill slots for each assignment, so the second return sees the original value (42) instead of the new one (666). Worse, if the stack frame has been freed, the restored context executes on dangling memory — the kind of bug that produces no usable stack trace and is trivially weaponizable.

Fil-C Stacks Don't Dangle

Fil-C's approach is not "add more checks" — it's a fundamentally different stack management model. When you call setjmp or getcontext, Fil-C pins the relevant stack frames so they cannot be freed or reused while any saved context points to them. Attempting to longjmp to a context whose stack has already been retired is a safety error that panics, not silent corruption. The same applies to makecontext/swapcontext: if you free the stack that a context references, the next swapcontext to that context panics rather than resumes on garbage.

Even argument-ordering bugs are caught. Calling swapcontext with the executing context as the second argument (confusing first and second) is a common mistake. In yolo-C (standard unsafe C), this can behave like a longjmp or, with the right timing, execute on a dangling stack. In Fil-C, it's always a panic — deterministic, auditable, and safe.

What This Unlocks

The ucontext APIs power Boost.Fiber, many coroutine libraries, and handwritten fiber schedulers. Darwin deprecated them because they were too dangerous to maintain. Fil-C proves a memory-safe alternative exists without sacrificing performance or compatibility — the APIs behave exactly as before, except they cannot corrupt memory. Anyone building async execution in C, or porting legacy code that uses setjmp for exception handling, now has a path that doesn't require rewriting the entire stack.

Fil-C's approach raises the floor for what "portable C" can guarantee. If the compiler knows that stack frames are immortal until all saved contexts expire, it can stop inserting dubious spill-slot reuse optimizations around setjmp boundaries. That means volatile may eventually become unnecessary for correctness here — a welcome deprecation for anyone tired of sprinkling it over every local in a setjmp region.


Source: Memory Safe Context Switching (longjmp, setjmp) in Fil-C
Domain: fil-c.org

Read original source ->

External source stays available while the OJO article and comment thread stay local.

Comments load interactively on the live page.