scan: follow a word only if it could be a heap block's start - 16-aligned, in the user address space, not in the arena
The exit scan crashed two of the gate's scenarios (world, swim: SIGBUS and SIGSEGV in lp_mem_scan at 0x0e00000c65800000 and 0x04000004e461c000): a word of data with its high bits set was handed to malloc_size, and a zone faulted looking it up. A candidate must now be 16-aligned, at or above 4 GB (macOS's page zero), below 2^47, and outside the frame arena before malloc_size sees it; a block's own words are read only once malloc_size has said it is one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5aa7c03022
commit
91f91716b5
3 changed files with 47141 additions and 47087 deletions
|
|
@ -1265,13 +1265,22 @@ function emit_fence_frame() -> void {
|
||||||
emith("no:\n")
|
emith("no:\n")
|
||||||
emith(" ret i1 0\n")
|
emith(" ret i1 0\n")
|
||||||
emith("}\n")
|
emith("}\n")
|
||||||
|
emith("; a candidate is followed only if it could be a heap block's start: 16-aligned (malloc's), inside the\n")
|
||||||
|
emith("; user address space (above the first 4 GB, below 2^47 - a word with high bits is data, and some\n")
|
||||||
|
emith("; zones fault looking one up), and not in the frame arena; only then does malloc_size look at it\n")
|
||||||
emith("define internal void @lp_visit(i64 %w) {\n")
|
emith("define internal void @lp_visit(i64 %w) {\n")
|
||||||
emith("entry:\n")
|
emith("entry:\n")
|
||||||
emith(" %z = icmp eq i64 %w, 0\n")
|
emith(" %al = and i64 %w, 15\n")
|
||||||
emith(" %al = and i64 %w, 7\n")
|
|
||||||
emith(" %mis = icmp ne i64 %al, 0\n")
|
emith(" %mis = icmp ne i64 %al, 0\n")
|
||||||
emith(" %skip = or i1 %z, %mis\n")
|
emith(" %low = icmp ult i64 %w, 4294967296\n")
|
||||||
emith(" br i1 %skip, label %out, label %size\n")
|
emith(" %high = icmp uge i64 %w, 140737488355328\n")
|
||||||
|
emith(" %s1 = or i1 %mis, %low\n")
|
||||||
|
emith(" %s2 = or i1 %s1, %high\n")
|
||||||
|
emith(" br i1 %s2, label %out, label %arena\n")
|
||||||
|
emith("arena:\n")
|
||||||
|
emith(" %wp = inttoptr i64 %w to ptr\n")
|
||||||
|
emith(" %inar = call i1 @lp_in_arena(ptr %wp)\n")
|
||||||
|
emith(" br i1 %inar, label %out, label %size\n")
|
||||||
emith("size:\n")
|
emith("size:\n")
|
||||||
emith(" %p = inttoptr i64 %w to ptr\n")
|
emith(" %p = inttoptr i64 %w to ptr\n")
|
||||||
emith(" %sz = call i64 @malloc_size(ptr %p)\n")
|
emith(" %sz = call i64 @malloc_size(ptr %p)\n")
|
||||||
|
|
|
||||||
47119
selfhost/ludicc.seed.ll
47119
selfhost/ludicc.seed.ll
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue