Seen once on extended_checks (windows, 64) "Test ser/deser" for PR #3436 (tip 5aff6a3); a plain re-run of the same job on the same commit passed, linux extended_checks and local Windows runs of the same lane are green — nondeterministic, heap-layout dependent.
Crash
During the --deser pass, right after tests/jit_tests/assert.das (new in #3433 — first time the ser/deser lane serializes the jit_tests programs):
CRASH: EXCEPTION_ACCESS_VIOLATION (0xC0000005), reading address 0x0
das::TypeDecl::getMangledName
das::DebugInfoHelper::makeTypeInfo
das::DebugInfoHelper::makeVariableDebugInfo
das::DebugInfoHelper::makeStructureDebugInfo
das::rtti_builtin_module_for_each_structure
jit_register_Module_Rtti (JIT'd test code)
... pinvoke / runWithCatch / dastest deserialize_path (dastest.das:436/444)
A JIT'd test walks structures of a deserialized module via RTTI and getMangledName dereferences a null TypeDecl link.
Suspected mechanism
The dastest rail (rtti_ast_serializer_deserialize_program) deserializes under a gc_guard, whose destructor sweeps unclaimed nodes — and the guard scope ends before the test callback (simulate + run) executes. Survival of the deserialized AST relies on finalizeModule's collect moving nodes onto module roots, but the already_exists path deliberately skips that:
// module_builtin_ast_serialize.cpp, finalizeModule
} else {
// we DO NOT collect something which is "already exists"
// we leave it hanging, and we keep links to types from other modules and let them claim
// this_mod->gc_collect(gc_root::gc_get_active_root());
}
Any node reachable from a surviving module but not claimed by a later module's collect gets swept with the guard while still referenced — a dangling AST link that reads as intact memory (reuse cache) until allocation timing says otherwise. Same corruption class as the env-rail dangling-active-root bug fixed in #3436, one rail over.
A DAS_GC_DEBUG=1 run of the dastest --ser/--deser lane (not just tests-cpp) with the jit_tests included should turn the nondeterministic AV into a deterministic poisoned-read and pinpoint the unclaimed node.
🤖 Generated with Claude Code
Seen once on
extended_checks (windows, 64)"Test ser/deser" for PR #3436 (tip 5aff6a3); a plain re-run of the same job on the same commit passed, linux extended_checks and local Windows runs of the same lane are green — nondeterministic, heap-layout dependent.Crash
During the
--deserpass, right aftertests/jit_tests/assert.das(new in #3433 — first time the ser/deser lane serializes the jit_tests programs):A JIT'd test walks structures of a deserialized module via RTTI and
getMangledNamedereferences a nullTypeDecllink.Suspected mechanism
The dastest rail (
rtti_ast_serializer_deserialize_program) deserializes under agc_guard, whose destructor sweeps unclaimed nodes — and the guard scope ends before the test callback (simulate + run) executes. Survival of the deserialized AST relies onfinalizeModule's collect moving nodes onto module roots, but thealready_existspath deliberately skips that:Any node reachable from a surviving module but not claimed by a later module's collect gets swept with the guard while still referenced — a dangling AST link that reads as intact memory (reuse cache) until allocation timing says otherwise. Same corruption class as the env-rail dangling-active-root bug fixed in #3436, one rail over.
A
DAS_GC_DEBUG=1run of the dastest--ser/--deserlane (not just tests-cpp) with the jit_tests included should turn the nondeterministic AV into a deterministic poisoned-read and pinpoint the unclaimed node.🤖 Generated with Claude Code