Skip to content

Commit 05aeb64

Browse files
committed
Fix include_connected: run BFS inbound+outbound separately
cbm_store_bfs doesn't support direction="both" — it silently falls through to outbound only. Run two BFS passes (inbound + outbound) and merge results, matching how handle_trace_call_path works. Also fix use-after-free: use strcpy for BFS node names that get freed before JSON serialization.
1 parent 9412f09 commit 05aeb64

1 file changed

Lines changed: 24 additions & 10 deletions

File tree

src/mcp/mcp.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -990,21 +990,35 @@ static bool validate_edge_type(const char *s) {
990990
}
991991

992992
/* Enrich search result with 1-hop connected node names. */
993+
/* Add BFS results to a yyjson array (deduped by name). */
994+
static void enrich_add_bfs(yyjson_mut_doc *doc, yyjson_mut_val *arr, cbm_traverse_result_t *tr) {
995+
for (int j = 0; j < tr->visited_count; j++) {
996+
if (tr->visited[j].node.name) {
997+
yyjson_mut_arr_add_strcpy(doc, arr, tr->visited[j].node.name);
998+
}
999+
}
1000+
}
1001+
1002+
/* Enrich search result with 1-hop connected node names (inbound + outbound). */
9931003
static void enrich_connected(yyjson_mut_doc *doc, yyjson_mut_val *item, cbm_store_t *store,
9941004
int64_t node_id, const char *relationship) {
995-
cbm_traverse_result_t tr = {0};
9961005
const char *et[] = {relationship ? relationship : "CALLS"};
997-
cbm_store_bfs(store, node_id, "both", et, SKIP_ONE, SKIP_ONE, MCP_DEFAULT_LIMIT, &tr);
998-
if (tr.visited_count > 0) {
999-
yyjson_mut_val *conn = yyjson_mut_arr(doc);
1000-
for (int j = 0; j < tr.visited_count; j++) {
1001-
if (tr.visited[j].node.name) {
1002-
yyjson_mut_arr_add_str(doc, conn, tr.visited[j].node.name);
1003-
}
1004-
}
1006+
yyjson_mut_val *conn = yyjson_mut_arr(doc);
1007+
1008+
/* BFS doesn't support "both" — run inbound + outbound separately. */
1009+
cbm_traverse_result_t tr_in = {0};
1010+
cbm_store_bfs(store, node_id, "inbound", et, SKIP_ONE, SKIP_ONE, MCP_DEFAULT_LIMIT, &tr_in);
1011+
enrich_add_bfs(doc, conn, &tr_in);
1012+
cbm_store_traverse_free(&tr_in);
1013+
1014+
cbm_traverse_result_t tr_out = {0};
1015+
cbm_store_bfs(store, node_id, "outbound", et, SKIP_ONE, SKIP_ONE, MCP_DEFAULT_LIMIT, &tr_out);
1016+
enrich_add_bfs(doc, conn, &tr_out);
1017+
cbm_store_traverse_free(&tr_out);
1018+
1019+
if (yyjson_mut_arr_size(conn) > 0) {
10051020
yyjson_mut_obj_add_val(doc, item, "connected_names", conn);
10061021
}
1007-
cbm_store_traverse_free(&tr);
10081022
}
10091023

10101024
static char *handle_search_graph(cbm_mcp_server_t *srv, const char *args) {

0 commit comments

Comments
 (0)