--- id: "bug-562" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "lib" severity: "crash" timestamp: "2026-06-14T23:55:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/lib/request.c"] tags: ["use-after-free", "asan", "capnp", "encode_RequestReply", "redirect_host", "init_reply_by_req", "ha", "joblist", "uninitialized-stack"] related: [] legacy: true --- # bug-562: AddressSanitizer: heap-use-after-free in encode_RequestReply / strlen… ## Description AddressSanitizer: heap-use-after-free in encode_RequestReply / strlen (lib/controller.capnp.c:13168) on ctrl-2 startup, via xce_reply->xce_encode from OPCode_nop handler (cluster.c:307). Also: job submission succeeds but joblist shows no jobs. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause init_reply_by_req() only set seq+opcode, leaving the rest of the stack-declared xce_reply_t uninitialized. The Cap'n-C generated encode_RequestReply reads the common trailer field redirect_host UNCONDITIONALLY (gated only on != NULL), so a garbage stack pointer in reply.redirect_host was strlen'd. The garbage aliased a 4KB capnp segment freed moments earlier by the WAL-ack reply encode on the same thread -> UAF. Handlers that build a reply via init_reply_by_req and only set status/data_which/data (e.g. the NOP/state-report path) never cleared redirect_host. Empty joblist is downstream: ctrl-2 crash-looping on this UAF destabilizes replication/quorum, so a get request that fails over to the not-caught-up standby reads an empty jobmgr (standby serves get from its own committed state). ## Fix memset(reply,0,sizeof(*reply)) at the top of init_reply_by_req() (src/lib/request.c) before setting seq/opcode. All 30+ reply sites follow declare->init->populate, so zeroing in the shared initializer fixes the whole class (redirect_host/redirect_port/status/data garbage) at the source. Added regression test test_init_reply_by_req_zeroes_reply in src/lib/testsuite/test_request.c (poisons reply with 0xFF, asserts redirect_host==NULL etc). ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._