fix(controller): CtrlHelloRequest.key Data field crashed HA leader election (bug-1835)

CtrlHelloRequest.key was declared `Data` in controller.capnp. This
project's capnp-c backend silently no-ops encoding of Data-typed fields
without zero-initializing the caller's local struct, leaving an
uninitialized capn_ptr that write_CtrlHelloRequest unconditionally wrote
to the wire -- SIGSEGV in capn_setp/copy_ptr. Hit live: ctrl-1 won its
Raft election and crashed calling ha_send_ctrlhello_to_all_standbys().

Same bug class as bug-1504/bug-1505, both already fixed by switching the
field from Data to List(UInt8); bug-1505's own writeup had flagged
CtrlHelloRequest.key as a known-but-unfixed instance. Applied the
identical fix here: Data -> List(UInt8) + keyLen companion in the schema,
uint8_t*/key_len in typemap.h. The field is unused in production (always
NULL), so no consumer code changed. Added a round-trip regression test
covering both the NULL-key production shape and real key content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-09-21 03:51:48 +00:00
parent 1e43345b2e
commit cd9ecb4159
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
7 changed files with 197 additions and 21 deletions

View file

@ -623,9 +623,12 @@ struct heartbeat_msg_s {
/* CtrlHello state sync (Req 6.5, 6.6, 6.7) */
struct ctrl_hello_req_s {
char *name; /* standby's logical name */
xce_data_t *key; /* SHA-256(cluster_name + shared_secret) auth key */
uint8_t *key; /* SHA-256(cluster_name + shared_secret) auth key,
* malloc'd, or NULL; wire type is List(UInt8),
* not Data (see controller.capnp's own comment) */
uint64_t applied_lsn; /* standby's last applied WAL LSN */
uint64_t config_tag; /* standby's current config tag */
uint32_t key_len; /* length of key */
};
struct ctrl_hello_reply_s {