From 1ad7556fac33bca7300d2ede36d57551b6ecffaa Mon Sep 17 00:00:00 2001 From: Andrew Hundt Date: Fri, 26 Jun 2026 22:37:03 -0400 Subject: [PATCH] fix(graph_buffer): retain DB on relative root_path (was false-deleted) (#57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The post-dump verify (B1 mitigation, 63de254) used the strict cbm_store_check_integrity, which treats a non-absolute root_path (e.g. a relative repo_path like ".") as bad_root_path → the verify DELETED a valid DB. Indexing with a relative path therefore failed (status=error) — caught by self-indexing the repo (cbm cli index_repository repo_path="."); the same index with an absolute path succeeded cleanly (14723 nodes). Switch the verify to cbm_store_check_integrity_full with the path_only out-param: a path-only defect (cosmetic root_path) is RETAINED, consistent with #557 resolve_store — only genuine structural corruption (>5 project rows) is deleted. Verified: relative-path index now returns status=indexed; absolute-path index unchanged. test_graph_buffer gbuf_dump_relative_root_path_retained locks this in. graph_buffer 50 pass. Signed-off-by: Andrew Hundt --- src/graph_buffer/graph_buffer.c | 14 +++++++++++--- tests/test_graph_buffer.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/graph_buffer/graph_buffer.c b/src/graph_buffer/graph_buffer.c index 61b4bbbc1..e5dbc213b 100644 --- a/src/graph_buffer/graph_buffer.c +++ b/src/graph_buffer/graph_buffer.c @@ -1534,13 +1534,21 @@ int cbm_gbuf_dump_to_sqlite(cbm_gbuf_t *gb, const char *path) { * intermittently emit a structurally-corrupt .db (gbuf-data corruption that * is ASan/TSan-invisible). Detect it with the fast projects-table check * (O(1), not a full integrity_check) and remove the corrupt DB so neither - * queries nor tests ever read garbage — the next access re-indexes. */ + * queries nor tests ever read garbage — the next access re-indexes. + * + * Use the _full variant so a path-only defect (root_path the check considers + * non-absolute, e.g. a relative repo_path like ".") is RETAINED, not deleted + * — the node/edge data is intact and queries key off project name, not + * root_path. Deleting on path-only would drop valid DBs whenever a relative + * path is indexed (caught by self-indexing the repo with repo_path="."). + * Consistent with #557 resolve_store. */ if (rc == 0) { cbm_store_t *verify = cbm_store_open_path((const char *)path); if (verify) { - bool intact = cbm_store_check_integrity(verify); + bool path_only = false; + bool intact = cbm_store_check_integrity_full(verify, &path_only); cbm_store_close(verify); - if (!intact) { + if (!intact && !path_only) { /* genuine structural corruption only */ char nodes_str[CBM_SZ_16]; char edges_str[CBM_SZ_16]; snprintf(nodes_str, sizeof(nodes_str), "%d", node_idx); diff --git a/tests/test_graph_buffer.c b/tests/test_graph_buffer.c index 543e597b1..7d2bb3810 100644 --- a/tests/test_graph_buffer.c +++ b/tests/test_graph_buffer.c @@ -1047,6 +1047,35 @@ TEST(gbuf_dump_pipeline_path_integrity) { PASS(); } +/* Regression: a RELATIVE root_path (e.g. ".") must not cause the post-dump + * verify to delete a valid DB. The integrity check flags non-absolute + * root_paths as bad_root_path, but that's a cosmetic project-row defect + * (path_only) — the node/edge data is intact. The dump-verify must RETAIN + * (path_only) like #557, not delete. Caught by self-indexing the repo with + * repo_path="." (which failed with status=error before the fix). */ +TEST(gbuf_dump_relative_root_path_retained) { + char path[256]; + ASSERT_EQ(gbuf_make_temp_db(path, sizeof(path)), 0); + + cbm_gbuf_t *gb = cbm_gbuf_new("proj", "."); + ASSERT_NOT_NULL(gb); + cbm_gbuf_upsert_node(gb, "Function", "main", "proj.main", "main.c", 1, 2, "{}"); + + /* Must succeed (DB retained) despite the relative "." root_path. */ + ASSERT_EQ(cbm_gbuf_dump_to_sqlite(gb, path), 0); + + /* The DB file must still exist (not deleted by the verify). */ + FILE *f = fopen(path, "rb"); + ASSERT_NOT_NULL(f); + if (f) { + fclose(f); + } + + unlink(path); + cbm_gbuf_free(gb); + PASS(); +} + SUITE(graph_buffer) { /* Original tests */ RUN_TEST(gbuf_create_free); @@ -1110,4 +1139,6 @@ SUITE(graph_buffer) { /* B1 pipeline-path isolation (#23) */ RUN_TEST(gbuf_dump_pipeline_path_integrity); + /* Relative root_path retain regression (#57 self-index finding) */ + RUN_TEST(gbuf_dump_relative_root_path_retained); }