fix(runtime): don't deref a poisoned class's NULL fmap during migration
- wo_schema_diff poisons a class (fmap=NULL, new_cid=NONE) when a referenced/nested type changed or a field type is incompatible — the field-level map does not apply and wo_wal_migrate transcodes it instead. - main.c's pre-migration "migrating `X`: +/-fields" print loop dereferenced fmap unconditionally, so a poisoned-but-field-added class (e.g. a wmux Window whose nested Vte gained fields) was a NULL read → SIGSEGV at boot, before the migrate call could refuse or transcode. - guard the field detail on fmap != NULL; for a poisoned class print "(a referenced type changed — cannot migrate in place)" and let wo_wal_migrate proceed. It then transcodes cleanly when no record blocks it — so an additive nested change (Vte +oscbuf +title) now migrates and the session replays, instead of crashing serve. - test_wal 5966/0; verified against the real WAL that crashed (recovers session `main`); wmux gate 52/0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 35efa214d20dd7b055910ae66e4bfcc6201821c9)
This commit is contained in:
parent
5e8e0960bc
commit
1d78e0fa70
1 changed files with 22 additions and 13 deletions
|
|
@ -338,6 +338,12 @@ int main(int argc, char **argv) {
|
|||
const wo_schema_class *ok = &stored->classes[c];
|
||||
fprintf(stderr, "wovm: %s: migrating `%.*s`:", wal_path,
|
||||
(int)ok->name_len, (const char *)ok->name);
|
||||
/* A poisoned class (a referenced/nested type changed, or a
|
||||
* field's type is incompatible) has fmap == NULL and
|
||||
* new_cid == NONE — the field-level diff does not apply.
|
||||
* Dereferencing fmap here was a NULL read (SEGV); name the
|
||||
* situation and let wo_wal_migrate below refuse cleanly. */
|
||||
if (plan.classes[c].fmap) {
|
||||
for (uint32_t f = 0; f < ok->field_cnt; f++)
|
||||
if (plan.classes[c].fmap[f] == -1)
|
||||
fprintf(stderr, " -%.*s", (int)ok->fields[f].name_len,
|
||||
|
|
@ -352,6 +358,9 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, " +%.*s", (int)nk->fields[f].name_len,
|
||||
(const char *)nk->fields[f].name);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, " (a referenced type changed — cannot migrate in place)");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
char *merr = NULL;
|
||||
|
|
|
|||
Loading…
Reference in a new issue