Stage D batch 2: fix silent error sites in log_words.c, resolve the flagged category-iii special case (FABRIC-3.md §XXXII.6)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s

log_word_set_level(), log_do_emit(), and log_emit_string() (7 sites
total) now log a diagnostic via log_message(LOG_ERROR, ...) before
setting vm->error, matching this file's own already-correct
log_str_emit() sibling and defer_words.c's gold-standard pattern.

log_word_append_raw() (backing (LOG-APPEND-RAW), 3 sites) resolved
differently per §XXXII.3's own triage note: its doc comment forbids
log_message() here (recursion into the log ring it writes to), but the
word can also be invoked by hand at the console -- console_println()
carries no such recursion risk and matches Stage B's policy for a
manual interactive invocation. Added the console.h include this
required.

Three-arch clean qemu acceptance passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
Robert Allan James
2026-09-15 16:53:18 -04:00
co-authored by Claude Sonnet 5
parent 5417ffb2bf
commit 1a8c0e4fcf
10 changed files with 27224 additions and 11 deletions
+56 -10
View File
@@ -18,6 +18,7 @@
#include "starkernel/log_region.h"
#include "starkernel/log_attrib.h" /* vm_log_attributed_vm() */
#include "starkernel/capsule_birth.h" /* capsule_vm_registry_get, VMRegistryEntry */
#include "starkernel/console.h" /* console_println() -- (LOG-APPEND-RAW) diagnostics */
#include <string.h> /* strlen */
#endif
@@ -45,7 +46,11 @@ static void log_word_debug(VM *vm) { vm_push(vm, (cell_t)LOG_DEBUG); }
*/
static void log_word_set_level(VM *vm)
{
if (vm->dsp < 0) { vm->error = 1; return; }
if (vm->dsp < 0) {
log_message(LOG_ERROR, "LOG-LEVEL!: stack underflow");
vm->error = 1;
return;
}
cell_t n = vm_pop(vm);
if (n < (cell_t)LOG_ERROR) n = (cell_t)LOG_ERROR;
if (n > (cell_t)LOG_DEBUG) n = (cell_t)LOG_DEBUG;
@@ -75,9 +80,17 @@ static void log_word_get_level(VM *vm)
static void log_do_emit(VM *vm, LogLevel level)
{
if (vm->rsp < 0) { vm->error = 1; return; }
if (vm->rsp < 0) {
log_message(LOG_ERROR, "(do-log-*): return-stack underflow");
vm->error = 1;
return;
}
uint8_t *data = (uint8_t *)(uintptr_t)vm->return_stack[vm->rsp];
if (!data) { vm->error = 1; return; }
if (!data) {
log_message(LOG_ERROR, "(do-log-*): NULL inline-string pointer");
vm->error = 1;
return;
}
uint8_t n = data[0];
/* advance IP before emitting so re-entrant calls see correct state */
size_t skip = 1 + (size_t)n;
@@ -106,12 +119,20 @@ static void log_emit_string(VM *vm, LogLevel level,
size_t pos = vm->input_pos;
size_t end = vm->input_length;
if (!src || pos > end) { vm->error = 1; return; }
if (!src || pos > end) {
log_message(LOG_ERROR, "LOG-*\": no input buffer");
vm->error = 1;
return;
}
if (pos < end && src[pos] == ' ') pos++;
size_t start = pos;
while (pos < end && src[pos] != '"') pos++;
if (pos >= end) { vm->error = 1; return; }
if (pos >= end) {
log_message(LOG_ERROR, "LOG-*\": unterminated string literal");
vm->error = 1;
return;
}
size_t n = pos - start;
if (n > 255) n = 255;
@@ -124,13 +145,21 @@ static void log_emit_string(VM *vm, LogLevel level,
/* Compilation: emit runtime word then inline [len][chars][pad] */
DictEntry *rt = vm_find_word(vm, rt_name, (size_t)rt_nlen);
if (!rt) { vm->error = 1; return; }
if (!rt) {
log_message(LOG_ERROR, "LOG-*\": runtime word '%.*s' not found", rt_nlen, rt_name);
vm->error = 1;
return;
}
vm_compile_word(vm, rt);
size_t skip = 1 + n;
size_t padded = (skip + (sizeof(cell_t) - 1)) & ~(sizeof(cell_t) - 1);
uint8_t *raw = (uint8_t *)vm_allot(vm, padded);
if (!raw) { vm->error = 1; return; }
if (!raw) {
log_message(LOG_ERROR, "LOG-*\": vm_allot failed");
vm->error = 1;
return;
}
raw[0] = (uint8_t)n;
for (size_t i = 0; i < n; i++) raw[1 + i] = (uint8_t)src[start + i];
for (size_t i = 1 + n; i < padded; i++) raw[i] = 0;
@@ -214,14 +243,31 @@ static void log_word_debug_str(VM *vm) { log_str_emit(vm, LOG_DEBUG); }
#ifdef __STARKERNEL__
static void log_word_append_raw(VM *vm)
{
if (vm->dsp < 3) { vm->error = 1; return; }
/* Diagnostics here go via console_println(), not log_message() -- this
* function's own doc comment above forbids log_message() (recursion
* into the log ring it writes to); console_println() carries no such
* risk and covers the "by hand at the console for a smoke test" case
* that same comment names (FABRIC-3.md §XXXII.6). */
if (vm->dsp < 3) {
console_println("(LOG-APPEND-RAW): stack underflow");
vm->error = 1;
return;
}
cell_t msg_u = vm_pop(vm);
cell_t msg_addr = vm_pop(vm);
cell_t timestamp = vm_pop(vm);
cell_t level = vm_pop(vm);
if (msg_u < 0) { vm->error = 1; return; }
if (msg_addr < 0 || (msg_addr + msg_u) > (cell_t)VM_MEMORY_SIZE) { vm->error = 1; return; }
if (msg_u < 0) {
console_println("(LOG-APPEND-RAW): negative message length");
vm->error = 1;
return;
}
if (msg_addr < 0 || (msg_addr + msg_u) > (cell_t)VM_MEMORY_SIZE) {
console_println("(LOG-APPEND-RAW): message address out of range");
vm->error = 1;
return;
}
const char *msg = (const char *)&vm->memory[msg_addr];