Fix out-of-bounds stack pushes/pops in four vendored word files (found during S-1a)
physics_freeze_words.c, dictionary_heat_diagnostic_words.c, physics_diagnostic_words.c, physics_benchmark_words.c treated dsp as a count (data_stack[dsp++] push, data_stack[--dsp] pop) while the VM's dsp is the top index. On an empty stack a push wrote data_stack[-1], 8 bytes before the VM struct -- POST's DECAY-RATE@ test did it every boot (on aarch64 it hit parity.c's counter, elsewhere the POST block RAM tail). All 28 sites now use vm_pop/vm_push; four one-item guards fixed (dsp<0). Evidence on amd64/aarch64/riscv64: bytes before the VM struct unchanged across POST; DECAY-RATE@ leaves 1 item; LOOKUP-STRATEGY! now works; G interleave, precedence, console under load, relay 3, dict_hash unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d6c90a6839
commit
9bf2e8ec95
@@ -77,9 +77,9 @@ void forth_HEAT_PERCENTILES(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
vm->data_stack[vm->dsp++] = vm->heat_threshold_25th;
|
||||
vm->data_stack[vm->dsp++] = vm->heat_threshold_50th;
|
||||
vm->data_stack[vm->dsp++] = vm->heat_threshold_75th;
|
||||
vm_push(vm, vm->heat_threshold_25th);
|
||||
vm_push(vm, vm->heat_threshold_50th);
|
||||
vm_push(vm, vm->heat_threshold_75th);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ void forth_LOOKUP_STRATEGY_FETCH(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
vm->data_stack[vm->dsp++] = (cell_t)vm->lookup_strategy;
|
||||
vm_push(vm, (cell_t)vm->lookup_strategy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,12 +116,12 @@ void forth_LOOKUP_STRATEGY_FETCH(VM *vm) {
|
||||
void forth_LOOKUP_STRATEGY_STORE(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
if (vm->dsp < 1) {
|
||||
if (vm->dsp < 0) { /* one item: dsp is the top index, -1 = empty */
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t strategy = vm->data_stack[--vm->dsp];
|
||||
cell_t strategy = vm_pop(vm);
|
||||
if (strategy == 0 || strategy == 1) {
|
||||
vm->lookup_strategy = (int)strategy;
|
||||
}
|
||||
@@ -204,12 +204,12 @@ void forth_SHOW_HEAT_OPTIMIZATION(VM *vm) {
|
||||
void forth_COMPARE_LOOKUPS(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
if (vm->dsp < 1) {
|
||||
if (vm->dsp < 0) { /* one item: dsp is the top index, -1 = empty */
|
||||
vm->error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t iterations = vm->data_stack[--vm->dsp];
|
||||
cell_t iterations = vm_pop(vm);
|
||||
if (iterations <= 0) {
|
||||
printf("Need positive iteration count\n");
|
||||
return;
|
||||
|
||||
@@ -91,13 +91,13 @@ extern size_t sf_fc_count[256];
|
||||
void forth_BENCH_DICT_LOOKUP(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
if (vm->dsp < 1) {
|
||||
if (vm->dsp < 0) { /* one item: dsp is the top index, -1 = empty */
|
||||
vm->error = 1;
|
||||
printf("BENCH-DICT-LOOKUP: Need iteration count on stack\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t iterations = vm->data_stack[--vm->dsp];
|
||||
cell_t iterations = vm_pop(vm);
|
||||
if (iterations < 1) {
|
||||
printf("BENCH-DICT-LOOKUP: iterations must be >= 1\n");
|
||||
return;
|
||||
|
||||
@@ -251,13 +251,13 @@ void forth_PHYSICS_CALC_KNOBS(VM *vm) {
|
||||
void forth_PHYSICS_BURN(VM *vm) {
|
||||
if (vm->error) return;
|
||||
|
||||
if (vm->dsp < 1) {
|
||||
if (vm->dsp < 0) { /* one item: dsp is the top index, -1 = empty */
|
||||
vm->error = 1;
|
||||
printf("PHYSICS-BURN: Need count on stack\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t burn_count = vm->data_stack[--vm->dsp];
|
||||
cell_t burn_count = vm_pop(vm);
|
||||
|
||||
if (burn_count < 1) {
|
||||
printf("PHYSICS-BURN: count must be >= 1\n");
|
||||
|
||||
@@ -89,8 +89,8 @@ void forth_FREEZE_WORD(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
return; /* Silently fail on invalid length */
|
||||
@@ -130,8 +130,8 @@ void forth_UNFREEZE_WORD(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
return;
|
||||
@@ -168,11 +168,11 @@ void forth_FROZEN_QUERY(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
vm->data_stack[vm->dsp++] = 0; /* Not frozen */
|
||||
vm_push(vm, 0); /* Not frozen */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -180,9 +180,9 @@ void forth_FROZEN_QUERY(VM *vm) {
|
||||
DictEntry *entry = name ? vm_find_word(vm, name, (size_t)len) : NULL;
|
||||
|
||||
if (entry && (entry->flags & WORD_FROZEN)) {
|
||||
vm->data_stack[vm->dsp++] = -1; /* True (frozen) */
|
||||
vm_push(vm, -1); /* True (frozen) */
|
||||
} else {
|
||||
vm->data_stack[vm->dsp++] = 0; /* False (not frozen) */
|
||||
vm_push(vm, 0); /* False (not frozen) */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,9 +208,9 @@ void forth_HEAT_STORE(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t heat = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
cell_t heat = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
return;
|
||||
@@ -245,11 +245,11 @@ void forth_HEAT_FETCH(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
vm->data_stack[vm->dsp++] = 0;
|
||||
vm_push(vm, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,9 +257,9 @@ void forth_HEAT_FETCH(VM *vm) {
|
||||
DictEntry *entry = name ? vm_find_word(vm, name, (size_t)len) : NULL;
|
||||
|
||||
if (entry) {
|
||||
vm->data_stack[vm->dsp++] = entry->execution_heat;
|
||||
vm_push(vm, entry->execution_heat);
|
||||
} else {
|
||||
vm->data_stack[vm->dsp++] = 0;
|
||||
vm_push(vm, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,8 +285,8 @@ void forth_SHOW_HEAT(VM *vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
cell_t len = vm->data_stack[--vm->dsp];
|
||||
cell_t caddr = vm->data_stack[--vm->dsp];
|
||||
cell_t len = vm_pop(vm);
|
||||
cell_t caddr = vm_pop(vm);
|
||||
|
||||
if (len <= 0 || len > WORD_NAME_MAX) {
|
||||
return;
|
||||
@@ -391,7 +391,7 @@ void forth_DECAY_RATE_FETCH(VM *vm) {
|
||||
}
|
||||
|
||||
/* Stack: ( -- rate ) */
|
||||
vm->data_stack[vm->dsp++] = (cell_t)DECAY_RATE_PER_US_Q16;
|
||||
vm_push(vm, (cell_t)DECAY_RATE_PER_US_Q16);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user