Skip to content

Commit 6a2b1f5

Browse files
DeusDatamariomeyer
andcommitted
Fix Laravel route false positives: extension scoping + path filter
Port of community fix (PR #65): - Scope source-based route extractors by file extension: Go routes only on .go, Express on .js/.ts, Laravel on .php, Ktor on .kt/.kts. Prevents cross-framework false positives (e.g. Ktor regex matching PHP Cache::get calls). - Filter Laravel route paths containing $ or : characters — these are cache keys or interpolated expressions, not URL paths. Laravel route parameters use {param} syntax, so valid routes are unaffected. Co-Authored-By: mariomeyer <mariomeyer@users.noreply.github.com>
1 parent f80d350 commit 6a2b1f5

2 files changed

Lines changed: 32 additions & 15 deletions

File tree

src/pipeline/httplink.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,14 @@ int cbm_extract_laravel_routes(const char *name, const char *qn, const char *sou
14221422
memcpy(r->path, p + match[2].rm_so, (size_t)plen);
14231423
r->path[plen] = '\0';
14241424

1425+
/* Skip non-route strings that match the regex but contain characters
1426+
* invalid in URL paths (e.g., cache keys, interpolated expressions).
1427+
* Laravel route parameters use {param} syntax, so valid routes pass. */
1428+
if (strchr(r->path, '$') || strchr(r->path, ':')) {
1429+
p += match[0].rm_eo;
1430+
continue;
1431+
}
1432+
14251433
strncpy(r->function_name, name ? name : "", sizeof(r->function_name) - 1);
14261434
strncpy(r->qualified_name, qn ? qn : "", sizeof(r->qualified_name) - 1);
14271435
count++;

src/pipeline/pass_httplinks.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -260,25 +260,34 @@ static int discover_node_routes(const cbm_gbuf_node_t *n, const cbm_pipeline_ctx
260260
}
261261
free_decorators(decs);
262262

263-
/* 2. Source-based routes (Go gin/chi, Express, Laravel, Ktor) */
263+
/* 2. Source-based routes — scoped by file extension to avoid
264+
* cross-framework false positives (e.g. Ktor regex matching PHP Cache::get) */
264265
if (n->file_path && n->start_line > 0 && n->end_line > 0 && total < max_out) {
265266
char *source = read_source_lines(ctx, n->file_path, n->start_line, n->end_line);
266267
if (source) {
267-
int nr = cbm_extract_go_routes(n->name, n->qualified_name, source, out + total,
268-
max_out - total);
269-
total += nr;
270-
271-
nr = cbm_extract_express_routes(n->name, n->qualified_name, source, out + total,
272-
max_out - total);
273-
total += nr;
274-
275-
nr = cbm_extract_laravel_routes(n->name, n->qualified_name, source, out + total,
276-
max_out - total);
277-
total += nr;
268+
const char *fp = n->file_path;
269+
int nr;
278270

279-
nr = cbm_extract_ktor_routes(n->name, n->qualified_name, source, out + total,
280-
max_out - total);
281-
total += nr;
271+
if (has_suffix(fp, ".go")) {
272+
nr = cbm_extract_go_routes(n->name, n->qualified_name, source, out + total,
273+
max_out - total);
274+
total += nr;
275+
}
276+
if (is_jsts_file(fp)) {
277+
nr = cbm_extract_express_routes(n->name, n->qualified_name, source, out + total,
278+
max_out - total);
279+
total += nr;
280+
}
281+
if (has_suffix(fp, ".php")) {
282+
nr = cbm_extract_laravel_routes(n->name, n->qualified_name, source, out + total,
283+
max_out - total);
284+
total += nr;
285+
}
286+
if (has_suffix(fp, ".kt") || has_suffix(fp, ".kts")) {
287+
nr = cbm_extract_ktor_routes(n->name, n->qualified_name, source, out + total,
288+
max_out - total);
289+
total += nr;
290+
}
282291

283292
free(source);
284293
}

0 commit comments

Comments
 (0)