From 25e962309fa9e805699ac7593ab86a0d5695fe6f Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Wed, 19 Aug 2026 10:34:25 +0000 Subject: [PATCH] chore(wolf): checkpoint buglog.json (979 bugs) --- .wolf/buglog.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.wolf/buglog.json b/.wolf/buglog.json index f0148de3..60b83430 100644 --- a/.wolf/buglog.json +++ b/.wolf/buglog.json @@ -17662,6 +17662,26 @@ ], "occurrences": 1, "last_seen": "2026-08-19T00:00:00Z" + }, + { + "id": "bug-1598", + "timestamp": "2026-08-19T00:00:00Z", + "error_message": "AddressSanitizer: stack-use-after-return on address inside `sim` (xce_sched_sim_driver_t) at cbuf_get, thread T2 (sim_picker_thread_fn), reading test_run_deactivates_tlog_virtual_clock_logging_on_completion's stack frame after it returned", + "file": "src/scheduler/testsuite/test_sim_event_loop.c", + "root_cause": "sched_sim_driver_run() (src/scheduler/src/sim_loop.c) spawns sim_picker_thread_fn on a real pthread that is, by this codebase's own documented design (that function's own header comment), never joined or cancelled -- no sim-driver teardown/fini function exists yet. It loops forever on cbuf_get(&sim->core.wbuf, ...), reading `sim` for the lifetime of the process. Every white-box test in test_sim_event_loop.c that calls sched_sim_driver_run()/sched_sim_driver_start() with a stack-local `xce_sched_sim_driver_t sim;` was therefore ALWAYS a latent stack-use-after-return once its test function returned -- it simply hadn't been caught yet, because no prior test ordering/stack-frame-reuse pattern had triggered ASAN's shadow-memory detector. Adding one new test (test_run_deactivates_tlog_virtual_clock_logging_on_completion, part of the scheduler-core design-review follow-up wiring tlog virtual-clock activation into sim.c/sim_loop.c) between two existing tests shifted the stack layout enough to make the pre-existing latent bug fire deterministically (reproduced on 2 independent runs).", + "fix": "Changed the fixture from stack-local to `static xce_sched_sim_driver_t sim;` storage in three places: test_run_processes_multiple_sessions_in_order_and_no_longer_returns_enosys(), test_run_deactivates_tlog_virtual_clock_logging_on_completion() (the test that first exposed it), and the run_sim_and_capture_stdout() helper (used once, by test_job_present_only_in_initial_snapshot_still_reaches_the_picker()). Safe specifically because: (a) sched_sim_driver_start() unconditionally memset()s the whole struct as its first action, so no stale-data leak across runs; (b) each affected function is called exactly once per test-binary process (verified via grep, no re-entrancy), so no second call's memset can ever stomp a still-live zombie thread's cbuf mutex/condvar state from a first call -- static would be UNSAFE on a helper called more than once while an earlier zombie thread might still be alive. Does NOT fix the underlying thread-lifecycle gap (still no join/cancel) -- that is a separate, larger, already-documented-as-deferred architectural item (a real sim-driver teardown/fini function). Verified via 2 independent direct runs of the rebuilt sched_sim_event_loop_test binary post-fix: 4 Tests, 0 Failures, clean exit code 0 both times, no ASAN abort.", + "tags": [ + "scheduler", + "asan", + "stack-use-after-return", + "thread-lifecycle", + "test-only", + "sim-driver", + "design-review-followup" + ], + "related_bugs": [], + "occurrences": 1, + "last_seen": "2026-08-19T00:00:00Z" } ] }