From bf000289db62a8c82038ce9e34debc75ce7e2f93 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 2 Oct 2026 12:57:26 -0600 Subject: [PATCH] raddbg: fix potentially stale cfg lookups, do not hash cfg IDs since they are just monotonically increasing --- build.sh | 4 ++-- src/base/base_strings.h | 2 ++ src/config/config_core.c | 33 +++++++++++++++++++++++---------- src/raddbg/raddbg_core.c | 10 +++++----- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/build.sh b/build.sh index 6ad190be..e40fd48f 100755 --- a/build.sh +++ b/build.sh @@ -9,12 +9,12 @@ if [[ "$#" == "0" ]]; then raddbg='1'; fi if [[ "$#" == "1" && "${release:-0}" == "1" ]]; then raddbg='1'; fi if [[ "${asan:-0}" == "1" ]]; then echo "[asan enabled]" - auto_compile_flags="-fsanitize=address" + auto_compile_flags="$auto_compile_flags -fsanitize=address" fi # --- Mix Git Commit ID ------------------------------------------------------- if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - auto_compile_flags="-DBUILD_GIT_HASH=\"$(git describe --always --dirty)\" -DBUILD_GIT_HASH_FULL=$(git rev-parse HEAD)" + auto_compile_flags="$auto_compile_flags -DBUILD_GIT_HASH=\"$(git describe --always --dirty)\" -DBUILD_GIT_HASH_FULL=$(git rev-parse HEAD)" fi # --- Compile/Link Line Definitions ------------------------------------------- diff --git a/src/base/base_strings.h b/src/base/base_strings.h index 27cdc9d1..349a8619 100644 --- a/src/base/base_strings.h +++ b/src/base/base_strings.h @@ -234,6 +234,8 @@ internal String8 str8f(Arena *arena, char *fmt, ...); #define push_str8f(arena, ...) str8f((arena), __VA_ARGS__) internal String8 push_cstr(Arena *arena, String8 str); // TODO(rjf): this is unnecessary - this is implied by `push_str8_copy`. need to remove. +#define sf(...) str8f((scratch.arena), __VA_ARGS__) + //////////////////////////////// //~ rjf: String <=> Integer Conversions diff --git a/src/config/config_core.c b/src/config/config_core.c index e58d5320..7d9f4cd4 100644 --- a/src/config/config_core.c +++ b/src/config/config_core.c @@ -184,19 +184,19 @@ cfg_node_from_id(CFG_ID id) } else { - U64 hash = u64_hash_from_str8(str8_struct(&id)); + U64 hash = id; U64 slot_idx = hash%cfg_ctx->id_slots_count; for(CFG_NodePtrNode *n = cfg_ctx->id_slots[slot_idx].first; n != 0; n = n->next) { if(n->v->id == id) { result = n->v; + cfg_ctx->last_accessed_id = id; + cfg_ctx->last_accessed = result; break; } } } - cfg_ctx->last_accessed_id = id; - cfg_ctx->last_accessed = result; return result; } @@ -619,7 +619,7 @@ cfg_node_alloc(CFG_State *state) { cfg_id_node = push_array(state->arena, CFG_NodePtrNode, 1); } - U64 hash = u64_hash_from_str8(str8_struct(&result->id)); + U64 hash = result->id; U64 slot_idx = hash%state->ctx.id_slots_count; DLLPushBack(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, cfg_id_node); cfg_id_node->v = result; @@ -632,7 +632,6 @@ internal void cfg_node_release(CFG_State *state, CFG_Node *node) { state->ctx.change_gen += 1; - Temp scratch = scratch_begin(0, 0); // rjf: unhook from context @@ -648,23 +647,37 @@ cfg_node_release(CFG_State *state, CFG_Node *node) // rjf: release all nodes for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next) { + // rjf: unpack node CFG_Node *c = n->v; - U64 hash = u64_hash_from_str8(str8_struct(&c->id)); + U64 hash = c->id; U64 slot_idx = hash%state->ctx.id_slots_count; + + // rjf: release string, recycle node cfg_string_release(state, c->string); SLLStackPush(state->free, c); + + // rjf: zero node's contents c->first = c->last = c->prev = c->parent = 0; c->id = 0; c->string = str8_zero(); - for(CFG_NodePtrNode *n = state->ctx.id_slots[slot_idx].first; n != 0; n = n->next) + + // rjf: remove from id -> node map + for(CFG_NodePtrNode *id_n = state->ctx.id_slots[slot_idx].first; id_n != 0; id_n = id_n->next) { - if(n->v == c) + if(id_n->v == c) { - DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, n); - SLLStackPush(state->free_id_node, n); + DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, id_n); + SLLStackPush(state->free_id_node, id_n); break; } } + + // rjf: if this was the last accessed node, clear that slot + if(c == state->ctx.last_accessed) + { + state->ctx.last_accessed = &cfg_nil_node; + state->ctx.last_accessed_id = 0; + } } scratch_end(scratch); diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 05e46e50..68a18e02 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -11861,13 +11861,13 @@ rd_frame(void) // if(rd_state->frame_depth == 1) { - CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); + CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), s("transient")); for(CFG_Node *tln = transient->first, *next = &cfg_nil_node; tln != &cfg_nil_node; tln = next) { next = tln->next; - if(str8_match(tln->string, str8_lit("immediate"), 0)) + if(str8_match(tln->string, s("immediate"), 0)) { - if(cfg_node_child_from_string(tln, str8_lit("hot")) == &cfg_nil_node) + if(cfg_node_child_from_string(tln, s("hot")) == &cfg_nil_node) { cfg_node_release(rd_state->cfg, tln); } @@ -11875,12 +11875,12 @@ rd_frame(void) } for(CFG_Node *tln = transient->first; tln != &cfg_nil_node; tln = tln->next) { - if(str8_match(tln->string, str8_lit("immediate"), 0)) + if(str8_match(tln->string, s("immediate"), 0)) { for(CFG_Node *child = tln->first, *next = &cfg_nil_node; child != &cfg_nil_node; child = next) { next = child->next; - if(str8_match(child->string, str8_lit("hot"), 0)) + if(str8_match(child->string, s("hot"), 0)) { cfg_node_release(rd_state->cfg, child); }