Skip to content

Commit 7d6b3af

Browse files
committed
Fix memory leak in resolve_store + Windows setenv build error
- resolve_store: verify project exists in database after opening; close store immediately if project is absent (prevents SQLite connection leak when querying deleted/empty projects) - test_userconfig.c: use cbm_setenv/cbm_unsetenv instead of raw POSIX setenv/unsetenv (fixes Windows build)
1 parent 605cd92 commit 7d6b3af

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

src/mcp/mcp.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,17 @@ static cbm_store_t *resolve_store(cbm_mcp_server_t *srv, const char *project) {
653653
project_db_path(project, path, sizeof(path));
654654
srv->store = cbm_store_open_path_query(path);
655655
if (srv->store) {
656-
/* Only update ownership and cached project name on successful open.
657-
* When the file is absent, store is NULL and current_project retains
658-
* its previous value so the next call correctly retries the open. */
656+
/* Verify the project actually exists in this database.
657+
* A .db file may exist but be empty (e.g., after delete_project on
658+
* Linux where unlink defers actual removal). Opening an empty/deleted
659+
* store without closing it leaks the SQLite connection. */
660+
cbm_project_t proj_verify = {0};
661+
if (cbm_store_get_project(srv->store, project, &proj_verify) != CBM_STORE_OK) {
662+
cbm_store_close(srv->store);
663+
srv->store = NULL;
664+
return NULL;
665+
}
666+
cbm_project_free_fields(&proj_verify);
659667
srv->owns_store = true;
660668
free(srv->current_project);
661669
srv->current_project = heap_strdup(project);

tests/test_integration.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,6 @@ TEST(integ_mcp_delete_project) {
410410
snprintf(args, sizeof(args), "{\"label\":\"Function\",\"project\":\"%s\"}", g_project);
411411
resp = call_tool("search_graph", args);
412412
ASSERT_NOT_NULL(resp);
413-
/* Guard returns "not indexed" error or "no project loaded"; either is correct */
414413
ASSERT_TRUE(strstr(resp, "total") != NULL || strstr(resp, "not indexed") != NULL ||
415414
strstr(resp, "no project loaded") != NULL);
416415
free(resp);

tests/test_userconfig.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ TEST(userconfig_global_via_env) {
7171
0);
7272

7373
/* Set env var, load, restore */
74-
setenv("XDG_CONFIG_HOME", xdg_dir, 1);
74+
cbm_setenv("XDG_CONFIG_HOME", xdg_dir, 1);
7575
cbm_userconfig_t *cfg = cbm_userconfig_load(NULL); /* no project dir */
76-
unsetenv("XDG_CONFIG_HOME");
76+
cbm_unsetenv("XDG_CONFIG_HOME");
7777

7878
ASSERT_NOT_NULL(cfg);
7979
ASSERT_EQ(cbm_userconfig_lookup(cfg, ".twig"), CBM_LANG_HTML);
@@ -110,9 +110,9 @@ TEST(userconfig_project_wins_over_global) {
110110
write_json(proj_path, "{\"extra_extensions\":{\".xyz\":\"rust\"}}"),
111111
0);
112112

113-
setenv("XDG_CONFIG_HOME", xdg_dir, 1);
113+
cbm_setenv("XDG_CONFIG_HOME", xdg_dir, 1);
114114
cbm_userconfig_t *cfg = cbm_userconfig_load(proj_dir);
115-
unsetenv("XDG_CONFIG_HOME");
115+
cbm_unsetenv("XDG_CONFIG_HOME");
116116

117117
ASSERT_NOT_NULL(cfg);
118118
/* Project definition (rust) must win */

0 commit comments

Comments
 (0)