diff --git a/src/pipeline/httplink.c b/src/pipeline/httplink.c index 4a936bc95..7d72c1c5e 100644 --- a/src/pipeline/httplink.c +++ b/src/pipeline/httplink.c @@ -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++; diff --git a/src/pipeline/pass_httplinks.c b/src/pipeline/pass_httplinks.c index ff367326f..7ecdda719 100644 --- a/src/pipeline/pass_httplinks.c +++ b/src/pipeline/pass_httplinks.c @@ -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); }