fix(controller): stop SIGSEGV in WalCatchupEntry capnp encode (bug-1505)
controller_unit_test crashed deterministically in write_WalCatchupEntry (test_wal_catchup_append_term_fields_round_trip) -- the same bug class as bug-1504 (SnapshotData.internalState): this codebase's capnpc-c backend silently no-ops Data-field encoding in generated encode_XXX() composite helpers without zero-initializing the caller's local struct first, leaving an uninitialized capn_ptr written onto the wire. Confirmed zero production exposure before fixing: xce_wal_batch_encode_ raw()/wal_entry_to_wire() (request.c) never call the generic encode_WalCatchupEntry() at all -- they memset() their own struct and call write_WalCatchupEntry() directly with every field hand-set, so this was 100% test-only exposure (grepped every caller of the generic encode/decode pair; only the crashing test uses it). Fix mirrors bug-1504: WalCatchupEntry.payload (@2) and batchPayloads (@10) switched from Data to List(UInt8) in controller.capnp (new batchPayloadsLen @11 companion; payload reuses the existing wirePayloadLen @9), typemap.h's wal_catchup_entry_t field types updated, and request.c's extract_data_bytes() widened to take a raw capn_ptr (it already only used .p internally) so its call sites work regardless of which Data-shaped wrapper the generated accessor returns now. batchPayloads' single-top-level-blob shape confirmed this does not reintroduce bug-847's per-element cross-segment far-pointer loss -- that issue is inherent to per-element data regardless of Data vs List(UInt8) spelling. Strengthened test_wal_catchup_append_term_fields_round_trip with real payload/batchPayloads content assertions -- previously never exercised, since the test's src fields were left NULL. Verified: controller suite 3/3 (was 2/3, crashing), scheduler suite unaffected at 37/37 (unrelated schema area). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JPPXeKSUXUqcqvzNXY1rzJ
This commit is contained in:
parent
829fbe41dc
commit
1fd467d072
7 changed files with 121 additions and 22 deletions
|
|
@ -195,11 +195,21 @@ static void test_request_vote_last_log_tuple_round_trip(void)
|
|||
/* ------------------------------------------------------------------ */
|
||||
/* Test 5: WalCatchupEntry (replication envelope) round-trips the */
|
||||
/* AppendEntries term fields (prev_log_index, prev_log_term, term) */
|
||||
/* (ha-term-safety task 1.1, Req 1.3/1.4). */
|
||||
/* (ha-term-safety task 1.1, Req 1.3/1.4), AND (bug-1505 fix) genuinely */
|
||||
/* round-trips payload/batchPayloads content through the GENERIC codec */
|
||||
/* now that both are List(UInt8) instead of Data -- this is the exact */
|
||||
/* path that used to SIGSEGV (write_WalCatchupEntry writing an */
|
||||
/* uninitialized capn_ptr for a no-op'd Data field) even though this */
|
||||
/* test never previously touched payload content at all (src.payload */
|
||||
/* stayed NULL); see controller.capnp's WalCatchupEntry.payload comment */
|
||||
/* for the full root cause. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void test_wal_catchup_append_term_fields_round_trip(void)
|
||||
{
|
||||
static const uint8_t entry_payload[] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
|
||||
static const uint8_t batch_payload[] = { 0xAA, 0xBB, 0xCC, 0xDD };
|
||||
|
||||
wal_catchup_entry_t src;
|
||||
memset(&src, 0, sizeof(src));
|
||||
src.lsn = 42ULL;
|
||||
|
|
@ -207,6 +217,12 @@ static void test_wal_catchup_append_term_fields_round_trip(void)
|
|||
src.term = 7ULL; /* NEW: this entry's term stamp */
|
||||
src.prev_log_index = 41ULL; /* NEW: lsn - 1 */
|
||||
src.prev_log_term = 6ULL; /* NEW: term at prev_log_index */
|
||||
/* bug-1505 fix: real content through the generic codec (List(UInt8),
|
||||
* not Data) for both payload and batchPayloads. */
|
||||
src.payload = (uint8_t *)entry_payload;
|
||||
src.wire_payload_len = (uint32_t)sizeof(entry_payload);
|
||||
src.batch_payloads = (uint8_t *)batch_payload;
|
||||
src.batch_payloads_wire_len = (uint32_t)sizeof(batch_payload);
|
||||
|
||||
struct capn c;
|
||||
capn_init_malloc(&c);
|
||||
|
|
@ -238,6 +254,20 @@ static void test_wal_catchup_append_term_fields_round_trip(void)
|
|||
TEST_ASSERT_EQUAL_UINT64(41ULL, dst.prev_log_index); /* survives the wire */
|
||||
TEST_ASSERT_EQUAL_UINT64(6ULL, dst.prev_log_term); /* survives the wire */
|
||||
|
||||
/* bug-1505 fix: payload/batchPayloads now genuinely round-trip through
|
||||
* the generic codec (List(UInt8), not Data) -- this is the content the
|
||||
* old no-op'd Data-field codec never actually carried. */
|
||||
TEST_ASSERT_EQUAL_UINT32((uint32_t)sizeof(entry_payload),
|
||||
dst.wire_payload_len);
|
||||
TEST_ASSERT_NOT_NULL(dst.payload);
|
||||
TEST_ASSERT_EQUAL_MEMORY(entry_payload, dst.payload, sizeof(entry_payload));
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT32((uint32_t)sizeof(batch_payload),
|
||||
dst.batch_payloads_wire_len);
|
||||
TEST_ASSERT_NOT_NULL(dst.batch_payloads);
|
||||
TEST_ASSERT_EQUAL_MEMORY(batch_payload, dst.batch_payloads,
|
||||
sizeof(batch_payload));
|
||||
|
||||
capn_free(&d);
|
||||
free(buf);
|
||||
printf("test_wal_catchup_append_term_fields_round_trip: PASS\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue