--- id: "bug-1769" status: "fixed" status_updated: "2026-09-25" status_note: "1ecd348f" component: "scheduler" severity: "crash" timestamp: "2026-09-04T00:00:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: [] tags: ["scheduler", "alter-resreq", "type-confusion", "heap-oob-read", "pre-existing", "severity-high", "untested", "scheduler-allocation-discovery"] related: ["bug-1768"] fix_commits: ["1ecd348f"] legacy: true --- # bug-1769: out-of-scope type confusion discovered during scheduler-allocation task 5.1's review… ## Description OPEN, NOT A CRASH (but reachable) -- pre-existing, out-of-scope type confusion discovered during scheduler-allocation task 5.1's review (cache/dispatch wiring). core_build_alter_schedobj() (src/scheduler/src/core_events.c) stores raw `xce_compound_schedobj_t*` (sizeof == 24 bytes) into `obj->u.alters` (an xlist_t), but sched_make_alter_allocation() (src/scheduler/src/scheduler.c) reads each entry back cast as `xce_sched_obj_t*` (sizeof == 176 bytes, with `offsetof(xce_sched_obj_t, u) == 136`) and dereferences `obj->u.compound->resreq` through that mis-typed pointer. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause CONFIRMED via direct code read at both the construction site (core_events.c) and the read site (scheduler.c), plus a compiled offsetof/sizeof probe against the real headers during task 5.1's review: this is a genuine struct-layout mismatch, not a false alarm -- the two types do not share a compatible prefix layout. Any real ALTER-tagged job (the resreq grammar's `{A} || {B}` alternate syntax legitimately produces XCE_RESREQ_ALTER per xce_resreq.peg) dereferencing through this cast reads ~112 bytes past the actual 24-byte allocation, an out-of-bounds heap read. Separately confirmed during the same investigation that test_snapshot_load_allocator_regression.c's header comment claiming to already exercise this ALTER path is itself mistaken: its `"type == any"` fixture has no `{`/`}` braces, so per xce_resreq.peg's grammar it parses as XCE_RESREQ_PRIMARY, not ALTER -- it never actually drives sched_make_alter_allocation()'s u.alters read path. No test anywhere in the tree currently constructs a real multi-entry u.alters list and drives it through sched_make_alter_allocation(), so this defect is both real and currently completely untested. ## Fix NOT FIXED -- discovered and characterized during scheduler-allocation task 5.1's independent review (2026-09-04); deliberately left out of that task's scheduler.c-dispatch boundary. Needs a dedicated bugfix task: either change core_build_alter_schedobj() to store properly-typed xce_sched_obj_t* entries into u.alters (matching what sched_make_alter_allocation() expects), or change sched_make_alter_allocation() to read xce_compound_schedobj_t* entries directly without the intermediate xce_sched_obj_t* cast. Should be paired with a new regression test that actually constructs an ALTER-tagged job (real `{A}||{B}` resreq syntax) and drives it end to end, since the existing test that was believed to cover this does not. ## Verification _Not recorded (migrated from buglog.json)._ ## References - Related: bug-1768