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>
This commit is contained in:
Martin Vogel
2026-03-20 18:42:44 +01:00
co-authored by mariomeyer
parent f80d35094b
commit 6a2b1f547f
2 changed files with 32 additions and 15 deletions
+8
View File
@@ -1422,6 +1422,14 @@ int cbm_extract_laravel_routes(const char *name, const char *qn, const char *sou
memcpy(r->path, p + match[2].rm_so, (size_t)plen);
r->path[plen] = '\0';
/* Skip non-route strings that match the regex but contain characters
* invalid in URL paths (e.g., cache keys, interpolated expressions).
* Laravel route parameters use {param} syntax, so valid routes pass. */
if (strchr(r->path, '$') || strchr(r->path, ':')) {
p += match[0].rm_eo;
continue;
}
strncpy(r->function_name, name ? name : "", sizeof(r->function_name) - 1);
strncpy(r->qualified_name, qn ? qn : "", sizeof(r->qualified_name) - 1);
count++;
+24 -15
View File
@@ -260,25 +260,34 @@ static int discover_node_routes(const cbm_gbuf_node_t *n, const cbm_pipeline_ctx
}
free_decorators(decs);
/* 2. Source-based routes (Go gin/chi, Express, Laravel, Ktor) */
/* 2. Source-based routes — scoped by file extension to avoid
* cross-framework false positives (e.g. Ktor regex matching PHP Cache::get) */
if (n->file_path && n->start_line > 0 && n->end_line > 0 && total < max_out) {
char *source = read_source_lines(ctx, n->file_path, n->start_line, n->end_line);
if (source) {
int nr = cbm_extract_go_routes(n->name, n->qualified_name, source, out + total,
const char *fp = n->file_path;
int nr;
if (has_suffix(fp, ".go")) {
nr = cbm_extract_go_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
nr = cbm_extract_express_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
nr = cbm_extract_laravel_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
nr = cbm_extract_ktor_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
total += nr;
}
if (is_jsts_file(fp)) {
nr = cbm_extract_express_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
}
if (has_suffix(fp, ".php")) {
nr = cbm_extract_laravel_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
}
if (has_suffix(fp, ".kt") || has_suffix(fp, ".kts")) {
nr = cbm_extract_ktor_routes(n->name, n->qualified_name, source, out + total,
max_out - total);
total += nr;
}
free(source);
}