Fix setjmp/longjmp table matching to survive raw jmp_buf save/restore#1297
Fix setjmp/longjmp table matching to survive raw jmp_buf save/restore#1297qianxichen233 wants to merge 2 commits into
Conversation
buf[0] previously stored the jmp_buf's own fixed address as the key testSetjmp matches against. For a jmp_buf that lives in a long-lived buffer and gets saved/restored as raw bytes by an unwind-protect-style helper (memcpy(&saved, &buf, sizeof(buf)) and back), the address never changes, so every registration on that buffer was indistinguishable. A caller that restores an older snapshot before re-throwing therefore kept matching its own already-fired registration, causing an unbounded catch/rethrow loop that silently exhausted the null-collected GC heap. Replace the address-based key with a fresh per-call monotonic token stored in buf[0], and stop clearing matched table entries (which broke legitimate repeated longjmps to a still-live buffer with no intervening setjmp). Tokens make raw byte restoration meaningful again: an outer, still-live registration's token correctly falls through the inner frame's table and resolves in the outer frame's own table, matching native register/stack snapshot restoration semantics.
|
Can you trigger another ci run? |
End-to-End Test ReportTest Previewgrate harnessGrate Test Report
Cases
static harnessTest ReportDeterministic TestsSummary
Test Results by Category
Fail TestsSummary
wasm harnessTest ReportDeterministic TestsSummary
Test Results by Category
Fail TestsSummary
Test Results by Category
C++ harnessSummary
Cases
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Yaxuan-w
left a comment
There was a problem hiding this comment.
Is that possible to have a unit test case for this?
| int token = ++g_setjmp_token; | ||
| if (token == 0) token = ++g_setjmp_token; /* skip the 0 sentinel on wraparound */ |
There was a problem hiding this comment.
In C, signed integer overflow is UB, so the program has already entered UB before we get to the if (token == 0) sentinel check. Maybe we can consider uint32_t in this case?
There was a problem hiding this comment.
theoritically this should never happen, gc heap overflow would happen before token overflow, as roughly ten million setjmp invocation would exhaust gc heap with even 4GB size (maximum possible size), an overflow of token would take 2 billion invocation
buf[0] previously stored the jmp_buf's own fixed address as the key testSetjmp matches against. For a jmp_buf that lives in a long-lived buffer and gets saved/restored as raw bytes by an unwind-protect-style helper (memcpy(&saved, &buf, sizeof(buf)) and back), the address never changes, so every registration on that buffer was indistinguishable. A caller that restores an older snapshot before re-throwing therefore kept matching its own already-fired registration, causing an unbounded catch/rethrow loop that silently exhausted the null-collected GC heap.
Replace the address-based key with a fresh per-call monotonic token stored in buf[0], and stop clearing matched table entries (which broke legitimate repeated longjmps to a still-live buffer with no intervening setjmp). Tokens make raw byte restoration meaningful again: an outer, still-live registration's token correctly falls through the inner frame's table and resolves in the outer frame's own table, matching native register/stack snapshot restoration semantics.