From 915ccb9cbac4b541efc83e698827c76409954765 Mon Sep 17 00:00:00 2001 From: romanornr <6548898+romanornr@users.noreply.github.com> Date: Fri, 8 May 2026 00:34:37 +0200 Subject: [PATCH] fix(c-lsp): cap expression type evaluation steps --- internal/cbm/lsp/c_lsp.c | 15 ++++++++++++--- internal/cbm/lsp/c_lsp.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/cbm/lsp/c_lsp.c b/internal/cbm/lsp/c_lsp.c index 2513a7d0..71d4229e 100644 --- a/internal/cbm/lsp/c_lsp.c +++ b/internal/cbm/lsp/c_lsp.c @@ -1204,11 +1204,20 @@ static const char* type_to_qn(const CBMType* t) { static const CBMType* c_eval_expr_type_inner(CLSPContext* ctx, TSNode node); +#define C_EVAL_DEPTH_LIMIT 256 +#define C_EVAL_MAX_STEPS_PER_FILE 10000 + const CBMType* c_eval_expr_type(CLSPContext* ctx, TSNode node) { if (ts_node_is_null(node)) return cbm_type_unknown(); - /* Guard against unbounded recursion on deeply nested C++ templates. - * Prevents stack overflow and NULL-deref from unusual AST shapes. */ - if (ctx->eval_depth > 256) { + /* Expression type evaluation is best-effort. Some recovery-mode C++ ASTs + * can repeatedly drive member/type lookup without increasing recursion + * depth. Keep a generous per-file work budget so pathological expressions + * degrade to unknown instead of hanging repository indexing. */ + if (ctx->eval_depth > C_EVAL_DEPTH_LIMIT || + ctx->eval_steps++ > C_EVAL_MAX_STEPS_PER_FILE) { + if (ctx->debug && ctx->eval_steps == C_EVAL_MAX_STEPS_PER_FILE + 2) { + fprintf(stderr, " [clsp] expression eval step budget exhausted; returning unknown\n"); + } return cbm_type_unknown(); } ctx->eval_depth++; diff --git a/internal/cbm/lsp/c_lsp.h b/internal/cbm/lsp/c_lsp.h index 51f10b3e..00832191 100644 --- a/internal/cbm/lsp/c_lsp.h +++ b/internal/cbm/lsp/c_lsp.h @@ -75,6 +75,7 @@ typedef struct { bool in_template; // currently inside template declaration bool debug; int eval_depth; // recursion depth for c_eval_expr_type (crash guard) + int eval_steps; // total expression eval calls for current file (hang guard) } CLSPContext; // --- API ---