Skip to content

Commit a8d6039

Browse files
fix(cross-repo): harden Maven library cleanup and growth
Signed-off-by: Pankaj Sharma <192576993+nvt-pankajsharma@users.noreply.github.com>
1 parent 1e9fd51 commit a8d6039

4 files changed

Lines changed: 239 additions & 145 deletions

File tree

src/mcp/mcp.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,14 +1815,10 @@ static void append_cross_repo_summary(yyjson_mut_doc *doc, yyjson_mut_val *root,
18151815
/* Scan edge types for any CROSS_* edges and sum them */
18161816
int cross_total = 0;
18171817
yyjson_mut_val *cr = yyjson_mut_obj(doc);
1818-
static const char *cross_types[] = {"CROSS_HTTP_CALLS",
1819-
"CROSS_ASYNC_CALLS",
1820-
"CROSS_CHANNEL",
1821-
"CROSS_GRPC_CALLS",
1822-
"CROSS_GRAPHQL_CALLS",
1823-
"CROSS_TRPC_CALLS",
1824-
"CROSS_LIBRARY_DEPENDS_ON",
1825-
"CROSS_LIBRARY_USED_BY"};
1818+
static const char *cross_types[] = {
1819+
"CROSS_HTTP_CALLS", "CROSS_ASYNC_CALLS", "CROSS_CHANNEL",
1820+
"CROSS_GRPC_CALLS", "CROSS_GRAPHQL_CALLS", "CROSS_TRPC_CALLS",
1821+
"CROSS_LIBRARY_DEPENDS_ON", "CROSS_LIBRARY_USED_BY"};
18261822
for (int t = 0; t < (int)(sizeof(cross_types) / sizeof(cross_types[0])); t++) {
18271823
for (int i = 0; i < schema->edge_type_count; i++) {
18281824
if (strcmp(schema->edge_types[i].type, cross_types[t]) == 0) {

src/pipeline/pass_cross_repo.c

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ static const char *cr_itoa(int v) {
4747
return cr_ibuf;
4848
}
4949

50+
bool cbm_cross_repo_project_list_alloc(char ***out, int cap, void *(*malloc_fn)(size_t)) {
51+
if (!out) {
52+
return false;
53+
}
54+
*out = NULL;
55+
if (cap <= 0 || !malloc_fn) {
56+
return false;
57+
}
58+
if ((size_t)cap > SIZE_MAX / sizeof(char *)) {
59+
return false;
60+
}
61+
char **items = malloc_fn((size_t)cap * sizeof(*items));
62+
if (!items) {
63+
return false;
64+
}
65+
*out = items;
66+
return true;
67+
}
68+
5069
/* ── Helpers ─────────────────────────────────────────────────────── */
5170

5271
static const char *cr_cache_dir(void) {
@@ -114,16 +133,14 @@ static void delete_cross_edges(cbm_store_t *store, const char *project) {
114133
cbm_store_delete_edges_by_type(store, project, "CROSS_GRAPHQL_CALLS");
115134
cbm_store_delete_edges_by_type(store, project, "CROSS_TRPC_CALLS");
116135
cbm_store_delete_edges_by_type(store, project, "CROSS_LIBRARY_DEPENDS_ON");
117-
cbm_store_delete_edges_by_type(store, project, "CROSS_LIBRARY_USED_BY");
118136
struct sqlite3 *db = cbm_store_get_db(store);
119137
if (!db) {
120138
return;
121139
}
122140
sqlite3_stmt *st = NULL;
123141
if (sqlite3_prepare_v2(db,
124-
"DELETE FROM nodes WHERE project=?1 AND "
125-
"(qualified_name GLOB '__library__*' OR "
126-
"qualified_name GLOB '__library_consumer__*')",
142+
"DELETE FROM nodes WHERE project=?1 AND label='Library' "
143+
"AND qualified_name GLOB '__library__*'",
127144
CBM_NOT_FOUND, &st, NULL) == SQLITE_OK) {
128145
sqlite3_bind_text(st, SKIP_ONE, project, CBM_NOT_FOUND, SQLITE_STATIC);
129146
sqlite3_step(st);
@@ -578,7 +595,12 @@ static int collect_all_projects(char ***out) {
578595

579596
int cap = CR_INIT_CAP;
580597
int count = 0;
581-
char **projects = malloc((size_t)cap * sizeof(char *));
598+
char **projects = NULL;
599+
if (!cbm_cross_repo_project_list_alloc(&projects, cap, malloc)) {
600+
cbm_closedir(d);
601+
*out = NULL;
602+
return 0;
603+
}
582604

583605
cbm_dirent_t *ent;
584606
while ((ent = cbm_readdir(d)) != NULL) {
@@ -593,15 +615,25 @@ static int collect_all_projects(char ***out) {
593615
continue;
594616
}
595617
if (count >= cap) {
596-
cap *= PAIR_LEN;
597-
char **tmp = realloc(projects, (size_t)cap * sizeof(char *));
618+
if (cap > INT32_MAX / PAIR_LEN) {
619+
break;
620+
}
621+
int new_cap = cap * PAIR_LEN;
622+
if ((size_t)new_cap > SIZE_MAX / sizeof(*projects)) {
623+
break;
624+
}
625+
char **tmp = realloc(projects, (size_t)new_cap * sizeof(*projects));
598626
if (!tmp) {
599627
break;
600628
}
629+
cap = new_cap;
601630
projects = tmp;
602631
}
603632
/* Strip .db extension */
604633
projects[count] = malloc(len - PAIR_LEN);
634+
if (!projects[count]) {
635+
break;
636+
}
605637
memcpy(projects[count], ent->name, len - CR_DB_EXT_LEN);
606638
projects[count][len - CR_DB_EXT_LEN] = '\0';
607639
count++;

src/pipeline/pass_cross_repo_maven.c

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ typedef struct {
2828
char *artifact_id;
2929
char *version;
3030
char *scope;
31-
char *relation;
32-
char *context_group_id;
33-
char *context_artifact_id;
3431
char *pom_path;
3532
} mcr_dependency_t;
3633

@@ -86,6 +83,9 @@ bool cbm_cross_repo_maven_grow_array(void **items, int *cap, size_t elem_size,
8683
return false;
8784
}
8885
int new_cap = *cap * PAIR_LEN;
86+
if ((size_t)new_cap > SIZE_MAX / elem_size) {
87+
return false;
88+
}
8989
void *tmp = realloc_fn(*items, (size_t)new_cap * elem_size);
9090
if (!tmp) {
9191
return false;
@@ -115,9 +115,6 @@ static void free_dependency_fields(mcr_dependency_t *dep) {
115115
free(dep->artifact_id);
116116
free(dep->version);
117117
free(dep->scope);
118-
free(dep->relation);
119-
free(dep->context_group_id);
120-
free(dep->context_artifact_id);
121118
free(dep->pom_path);
122119
memset(dep, 0, sizeof(*dep));
123120
}
@@ -370,12 +367,11 @@ static int list_pom_paths(cbm_store_t *store, const char *project, char ***out)
370367
continue;
371368
}
372369
if (count >= cap) {
373-
cap *= PAIR_LEN;
374-
char **tmp = realloc(paths, (size_t)cap * sizeof(char *));
375-
if (!tmp) {
370+
void *grown = paths;
371+
if (!cbm_cross_repo_maven_grow_array(&grown, &cap, sizeof(*paths), realloc)) {
376372
break;
377373
}
378-
paths = tmp;
374+
paths = grown;
379375
}
380376
paths[count] = malloc(strlen(path) + SKIP_ONE);
381377
if (paths[count]) {
@@ -438,16 +434,15 @@ static int collect_artifacts(cbm_store_t *store, const char *project, mcr_artifa
438434
}
439435
if (group && group[0] && artifact && artifact[0]) {
440436
if (count >= cap) {
441-
cap *= PAIR_LEN;
442-
mcr_artifact_t *tmp = realloc(items, (size_t)cap * sizeof(*items));
443-
if (!tmp) {
437+
void *grown = items;
438+
if (!cbm_cross_repo_maven_grow_array(&grown, &cap, sizeof(*items), realloc)) {
444439
free(parent_group);
445440
free(group);
446441
free(artifact);
447442
free(xml);
448443
break;
449444
}
450-
items = tmp;
445+
items = grown;
451446
}
452447
memset(&items[count], 0, sizeof(items[count]));
453448
items[count].group_id = group;
@@ -479,10 +474,10 @@ static int collect_artifacts(cbm_store_t *store, const char *project, mcr_artifa
479474

480475
static bool add_dependency(mcr_dependency_t **items, int *count, int *cap, const char *group,
481476
const char *artifact, const char *version, const char *scope,
482-
const char *relation, const char *context_group,
483-
const char *context_artifact, const char *pom_path) {
484-
if (!items || !*items || !count || !cap || !group || !artifact || !group[0] ||
485-
!artifact[0]) {
477+
const char *pom_path) {
478+
bool missing_storage = !items || !*items || !count || !cap;
479+
bool missing_coordinate = !group || !artifact || !group[0] || !artifact[0];
480+
if (missing_storage || missing_coordinate) {
486481
return false;
487482
}
488483
if (*count >= *cap) {
@@ -498,12 +493,8 @@ static bool add_dependency(mcr_dependency_t **items, int *count, int *cap, const
498493
dep->artifact_id = dup_cstr(artifact);
499494
dep->version = dup_cstr(version);
500495
dep->scope = dup_cstr(scope);
501-
dep->relation = dup_cstr(relation ? relation : "dependency");
502-
dep->context_group_id = dup_cstr(context_group);
503-
dep->context_artifact_id = dup_cstr(context_artifact);
504496
dep->pom_path = dup_cstr(pom_path);
505-
if (!dep->group_id || !dep->artifact_id || !dep->version || !dep->scope || !dep->relation ||
506-
!dep->context_group_id || !dep->context_artifact_id || !dep->pom_path) {
497+
if (!dep->group_id || !dep->artifact_id || !dep->version || !dep->scope || !dep->pom_path) {
507498
free_dependency_fields(dep);
508499
return false;
509500
}
@@ -564,28 +555,8 @@ static int collect_dependencies(cbm_store_t *store, const char *project, mcr_dep
564555
char *version = xml_tag_text_dup(open_end + SKIP_ONE, end, "version");
565556
char *scope = xml_tag_text_dup(open_end + SKIP_ONE, end, "scope");
566557

567-
add_dependency(&items, &count, &cap, group, artifact, version, scope, "dependency",
568-
group, artifact, paths[i]);
558+
add_dependency(&items, &count, &cap, group, artifact, version, scope, paths[i]);
569559

570-
const char *ex = open_end + SKIP_ONE;
571-
while ((ex = strstr(ex, "<exclusion")) != NULL && ex < end && count < MCR_MAX_EDGES) {
572-
const char *ex_open_end = strchr(ex, '>');
573-
if (!ex_open_end || ex_open_end >= end) {
574-
break;
575-
}
576-
const char *ex_end = strstr(ex_open_end + SKIP_ONE, "</exclusion>");
577-
if (!ex_end || ex_end > end) {
578-
break;
579-
}
580-
char *ex_group = xml_tag_text_dup(ex_open_end + SKIP_ONE, ex_end, "groupId");
581-
char *ex_artifact =
582-
xml_tag_text_dup(ex_open_end + SKIP_ONE, ex_end, "artifactId");
583-
add_dependency(&items, &count, &cap, ex_group, ex_artifact, version, scope,
584-
"exclusion", group, artifact, paths[i]);
585-
free(ex_group);
586-
free(ex_artifact);
587-
ex = ex_end + strlen("</exclusion>");
588-
}
589560
free(group);
590561
free(artifact);
591562
free(version);
@@ -607,8 +578,7 @@ static int64_t project_node_id(cbm_store_t *store, const char *project) {
607578
return 0;
608579
}
609580
sqlite3_stmt *st = NULL;
610-
if (sqlite3_prepare_v2(db,
611-
"SELECT id FROM nodes WHERE project=?1 AND label='Project' LIMIT 1",
581+
if (sqlite3_prepare_v2(db, "SELECT id FROM nodes WHERE project=?1 AND label='Project' LIMIT 1",
612582
CBM_NOT_FOUND, &st, NULL) != SQLITE_OK) {
613583
return 0;
614584
}
@@ -697,9 +667,6 @@ static char *build_library_props(const char *other_project, const mcr_dependency
697667
yyjson_mut_obj_add_strcpy(doc, root, "artifact_id", dep->artifact_id);
698668
yyjson_mut_obj_add_strcpy(doc, root, "version", dep->version);
699669
yyjson_mut_obj_add_strcpy(doc, root, "scope", dep->scope);
700-
yyjson_mut_obj_add_strcpy(doc, root, "relation", dep->relation);
701-
yyjson_mut_obj_add_strcpy(doc, root, "context_group_id", dep->context_group_id);
702-
yyjson_mut_obj_add_strcpy(doc, root, "context_artifact_id", dep->context_artifact_id);
703670
yyjson_mut_obj_add_strcpy(doc, root, "source_pom", dep->pom_path ? dep->pom_path : "");
704671

705672
size_t len = 0;
@@ -711,25 +678,23 @@ static char *build_library_props(const char *other_project, const mcr_dependency
711678
return json;
712679
}
713680

714-
static char *format_library_qn(const char *prefix, const char *project, const mcr_dependency_t *dep) {
681+
static char *format_library_qn(const char *prefix, const char *project,
682+
const mcr_dependency_t *dep) {
715683
if (!prefix || !project || !dep) {
716684
return NULL;
717685
}
718686
const char *pom_path = dep->pom_path ? dep->pom_path : "";
719-
int needed =
720-
snprintf(NULL, 0, "%s%s__%s__%s:%s__via__%s:%s__%s", prefix, project, dep->relation,
721-
dep->group_id, dep->artifact_id, dep->context_group_id, dep->context_artifact_id,
722-
pom_path);
687+
int needed = snprintf(NULL, 0, "%s%s__%s:%s__%s", prefix, project, dep->group_id,
688+
dep->artifact_id, pom_path);
723689
if (needed < 0) {
724690
return NULL;
725691
}
726692
char *qn = malloc((size_t)needed + SKIP_ONE);
727693
if (!qn) {
728694
return NULL;
729695
}
730-
snprintf(qn, (size_t)needed + SKIP_ONE, "%s%s__%s__%s:%s__via__%s:%s__%s", prefix, project,
731-
dep->relation, dep->group_id, dep->artifact_id, dep->context_group_id,
732-
dep->context_artifact_id, pom_path);
696+
snprintf(qn, (size_t)needed + SKIP_ONE, "%s%s__%s:%s__%s", prefix, project, dep->group_id,
697+
dep->artifact_id, pom_path);
733698
return qn;
734699
}
735700

0 commit comments

Comments
 (0)