Skip to content

SEGV in c_resolve_pending_template_calls: OOB read on NULL-terminated param_types array #215

@JasonDictos

Description

@JasonDictos

Bug

Indexing any repository containing nlohmann/json.hpp (or other heavily-templated C++ headers) crashes with a segfault in c_resolve_pending_template_calls.

Version

0.5.7 (also reproduced on current main)

Reproduction

# Minimal repo setup
mkdir -p /tmp/cbm-crash-repro && cd /tmp/cbm-crash-repro
git init
curl -sL https://github.com/nlohmann/json/releases/download/v3.12.0/json.hpp -o json.hpp
git add json.hpp && git commit -m "add nlohmann json"

# Crash
codebase-memory-mcp cli index_repository '{"repo_path":"/tmp/cbm-crash-repro"}'
# => Segmentation fault (core dumped)

Root Cause

param_types in CBMType.data.func is a NULL-terminated array (see type_rep.h:48), but two loops iterate using call_arg_count / arg_count as the bound instead of stopping at the NULL sentinel. When a template function is called with more arguments than formal parameters (common in heavily-templated C++ like nlohmann/json), this reads past the end of the array.

internal/cbm/lsp/c_lsp.c:304c_resolve_pending_template_calls:

for (int i = 0; i < call_arg_count; i++) {
    const CBMType* formal = callee->signature->data.func.param_types[i];
    if (!formal || !call_arg_types[i]) continue;  // BUG: should break on !formal, not continue

internal/cbm/lsp/type_registry.c:215score_overload_match:

for (int i = 0; i < arg_count; i++) {
    const CBMType* expected = f->signature->data.func.param_types[i];
    // ... same bug

Backtrace

#0  c_resolve_pending_template_calls () at internal/cbm/lsp/c_lsp.c:305
#1  c_resolve_calls_in_node () at internal/cbm/lsp/c_lsp.c:3200
#2  c_resolve_calls_in_node () [recursive]
#3  c_resolve_calls_in_node ()
#4  c_process_body_child ()
#5  c_lsp_process_file ()
#6  cbm_run_c_lsp ()
#7  cbm_extract_file () — source=nlohmann/json.hpp (967KB)
#8  extract_worker () at src/pipeline/pass_parallel.c:481

Fix

Change continue to break when hitting the NULL sentinel in both locations:

--- a/internal/cbm/lsp/c_lsp.c
+++ b/internal/cbm/lsp/c_lsp.c
@@ -303,7 +303,8 @@
         callee->signature->data.func.param_types) {
         for (int i = 0; i < call_arg_count; i++) {
             const CBMType* formal = callee->signature->data.func.param_types[i];
-            if (!formal || !call_arg_types[i]) continue;
+            if (!formal) break;  /* NULL-terminated array — stop, not skip */
+            if (!call_arg_types[i]) continue;

--- a/internal/cbm/lsp/type_registry.c
+++ b/internal/cbm/lsp/type_registry.c
@@ -214,8 +214,9 @@
     int score = 50;
     for (int i = 0; i < arg_count; i++) {
         const CBMType* expected = f->signature->data.func.param_types[i];
+        if (!expected) break;  /* NULL-terminated array — stop, not skip */
         const CBMType* actual = arg_types[i];
-        if (!expected || !actual || cbm_type_is_unknown(actual)) continue;
+        if (!actual || cbm_type_is_unknown(actual)) continue;

Tested: after the fix, the repo indexes successfully (4,178 nodes, 4,845 edges).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions