Fix SkHermesMessage payload-aliasing defect (task 3.8 findings log)
sk_hermes_send_one() -- the single funnel every sender, including sk_hermes_publish(), already goes through -- used to store the caller's own payload_addr pointer as-is. Two sends before either drains meant both messages pointed at the same caller-owned buffer, whichever send wrote last silently winning: real, confirmed live (a second identity thumbdrive attached at boot alongside Zuse's own left its WIREBIND pairing silently never happening). SkHermesMessage gains an inline payload_buf[SK_HERMES_CHUNK_MAX_ PAYLOAD] field; sk_hermes_send_one() now memcpy()s the caller's payload into it and points payload_addr at that copy instead. No sender or reader call site needed to change -- every existing reader already only ever reads through payload_addr, which still points at valid bytes of the same length, now message-owned. g_kh_blk_attach_buf/ g_kh_console_cmd_buf (repl.c, tasks 3.8/3.9) no longer need to survive past their own send call; their doc comments, which had claimed the old aliasing shape was benign, are corrected. Verified the original bug is actually gone: reproduced the exact original scenario (a real, sequentially-minted rajames identity attached at boot alongside Zuse's own, two simultaneous BLK-ATTACH- EVENT sends in one idle-loop pass) -- WIREBIND pairing, USE, and the Stage D relay all now work where WIREBIND previously silently failed. Standard three-ISA acceptance also clean: zero UNKNOWN WORD, dict_hash identical across all three and matching every prior acceptance run in this document. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
21734b1a52
commit
5c07745c18
+42
-25
@@ -362,12 +362,23 @@ static void sk_word_blk_attach_ack(VM *vm) {
|
||||
* own ATTACH-ACK-BUF (artemis:init.4th) is a raw CMOVE'd byte buffer
|
||||
* with no such guarantee, so this copies into its own NUL-terminated
|
||||
* buffer rather than passing ATTACH-ACK-BUF's address through
|
||||
* unchanged. Static, not stack-local: sk_hermes_send_one() stores
|
||||
* payload_addr out-of-line and the caller must keep it alive until
|
||||
* drained (kernel_hermes.h's own documented contract) -- same single-
|
||||
* buffer-reuse shape ATTACH-ACK-BUF itself already had (a second attach
|
||||
* before the first drains overwrites it), not a new hazard this
|
||||
* introduces. */
|
||||
* unchanged.
|
||||
*
|
||||
* CORRECTED 2026-09-22 (real defect, this task's own findings log):
|
||||
* this comment used to claim "static, not stack-local" was load-bearing
|
||||
* because sk_hermes_send_one() stored payload_addr out-of-line, the
|
||||
* caller having to keep it alive until drained -- and that a second
|
||||
* attach before the first drains overwriting this buffer was "the same
|
||||
* shape ATTACH-ACK-BUF itself already had, not a new hazard." That
|
||||
* claim was wrong: it WAS a new, real payload-aliasing defect (two
|
||||
* sends before either drains both pointing at this same buffer,
|
||||
* whichever wrote last silently winning), confirmed live and fixed at
|
||||
* the source (kernel_hermes.c's sk_hermes_send_one() now copies into
|
||||
* the message's own storage immediately, kernel_hermes.h's own doc
|
||||
* comment on SkHermesMessage has the full account). This buffer no
|
||||
* longer needs to survive past the KH-BLK-ATTACH-SEND call that sends
|
||||
* it -- staying `static` here is now just a convenience (avoids an
|
||||
* 80-byte stack frame), not a correctness requirement. */
|
||||
#define SK_KH_BLK_ATTACH_BUF_SIZE 80
|
||||
static char g_kh_blk_attach_buf[SK_KH_BLK_ATTACH_BUF_SIZE];
|
||||
|
||||
@@ -1387,25 +1398,31 @@ static int sk_repl_line_calls_use(const char *input)
|
||||
return (len == 3) || (input[len - 4] == ' ' || input[len - 4] == '\t');
|
||||
}
|
||||
|
||||
/* FABRIC-3.6.md task 3.9 -- static, not stack-local, for the same reason
|
||||
* g_kh_blk_attach_buf (task 3.8) is: sk_hermes_send_one() stores
|
||||
* payload_addr out-of-line and the caller must keep it alive until
|
||||
* drained. Sized to the largest single payload kernel-Hermes will ever
|
||||
* accept (SK_HERMES_CHUNK_MAX_PAYLOAD, task 3.5's one-block bound) --
|
||||
* console lines up to INPUT_BUFFER_SIZE-1 (1024) content bytes are
|
||||
* silently capped to SK_HERMES_CHUNK_MAX_PAYLOAD-1 (1023) to leave room
|
||||
* for the NUL terminator sk_hermes_drain_checkpoint() requires; chunking
|
||||
* a console line across multiple messages is out of this task's scope
|
||||
* (task 3.5 built the primitives, not a sender for this use) and the cap
|
||||
* is not expected to be reached by ordinary interactive typing. Only one
|
||||
* console-proxy session exists today (console.c's own singleton, per
|
||||
* memory project_multiseat_console_idea) so the single shared buffer
|
||||
* carries the same payload-aliasing defect g_kh_blk_attach_buf has
|
||||
* (FABRIC-3.6.md task 3.8's write-up wrongly called this shape benign;
|
||||
* corrected in the findings log, entry "found while starting task 3.9",
|
||||
* once task 3.8's own defect was found). Fix deferred: Captain Bob
|
||||
* ruled 2026-09-22 to land task 3.9's send-side cutover first and fix
|
||||
* the aliasing separately. */
|
||||
/* FABRIC-3.6.md task 3.9. Sized to the largest single payload
|
||||
* kernel-Hermes will ever accept (SK_HERMES_CHUNK_MAX_PAYLOAD, task
|
||||
* 3.5's one-block bound) -- console lines up to INPUT_BUFFER_SIZE-1
|
||||
* (1024) content bytes are silently capped to SK_HERMES_CHUNK_MAX_
|
||||
* PAYLOAD-1 (1023) to leave room for the NUL terminator
|
||||
* sk_hermes_drain_checkpoint() requires; chunking a console line across
|
||||
* multiple messages is out of this task's scope (task 3.5 built the
|
||||
* primitives, not a sender for this use) and the cap is not expected to
|
||||
* be reached by ordinary interactive typing.
|
||||
*
|
||||
* CORRECTED 2026-09-22 (real defect, found while starting this task,
|
||||
* fixed at the source): this comment originally justified `static, not
|
||||
* stack-local` on the claim that sk_hermes_send_one() stored
|
||||
* payload_addr out-of-line and the caller had to keep it alive until
|
||||
* drained -- which was true, and which g_kh_blk_attach_buf (task 3.8)
|
||||
* turned out to make into a genuine payload-aliasing defect (two sends
|
||||
* before either drains, whichever wrote last silently winning). Fixed
|
||||
* at the source (kernel_hermes.c's sk_hermes_send_one() now copies into
|
||||
* the message's own storage immediately, kernel_hermes.h's own doc
|
||||
* comment on SkHermesMessage has the full account) -- this buffer no
|
||||
* longer needs to survive past the send call, for this or any future
|
||||
* console-proxy session (console.c's own singleton today, per memory
|
||||
* project_multiseat_console_idea). Staying `static` is now just a
|
||||
* convenience (avoids a 1024-byte stack frame), not a correctness
|
||||
* requirement. */
|
||||
static char g_kh_console_cmd_buf[SK_HERMES_CHUNK_MAX_PAYLOAD];
|
||||
|
||||
static void sk_repl_dispatch_line(VM *vm, const char *input)
|
||||
|
||||
Reference in New Issue
Block a user