fix(graph_buffer): retain DB on relative root_path (was false-deleted) (#57)

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 <ATHundt@gmail.com>
This commit is contained in:
Andrew Hundt
2026-06-26 22:37:03 -04:00
parent 3b208736b3
commit 1ad7556fac
2 changed files with 42 additions and 3 deletions
+11 -3
View File
@@ -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);
+31
View File
@@ -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);
}