Skip to content

PHP: trait whose name collides with an aliased use … as import it composes → unbounded recursion in definitions pass, OOM (SIGKILL) #765

Description

@KasaharaDefries

Version

codebase-memory-mcp 0.8.1

Platform

macOS (Apple Silicon)

Install channel

GitHub release archive / install.sh / install.ps1

Binary variant

ui

What happened, and what did you expect?

A single ~6-line PHP trait drives the indexer into unbounded memory growth during the definitions pass: RSS climbs to ~50% of machine RAM (~18–20 GB on a 36 GB Mac) and the process is OOM-killed (SIGKILL, exit 137).

The trigger is a name collision between a trait and an aliased use … as … import that the trait composes:

  • trait Auditable
  • … that does use \Vendor\Pkg\Auditable as AuditableBase; (imported short name Auditable == trait name)
  • … and composes it with use AuditableBase;
  • … and has at least one method with a non-empty body.

The extractor appears to ignore the as alias and resolve the composed trait back to the same-short-name local trait — i.e. it sees trait Auditable composing Auditable (itself), a self-referential trait — then recurses without bound while expanding it to process a method body.

This reproduces with mode: fast, and with CBM_LSP_DISABLED=1 and CBM_DISABLE_LSP_CROSS=1 — so it is not in the LSP resolvers that received depth guards in #720. It is in the definitions pass and needs its own recursion/expansion guard.

Expected: the file indexes instantly (it's 6 lines), as it does the moment any one of the three ingredients is removed.

Reproduction

No proprietary code needed. Create a directory with one file Auditable.php:

<?php
namespace App\Demo;

use Vendor\Pkg\Auditable as AuditableBase;  // aliased import; short name "Auditable" == trait name below

trait Auditable {
    use AuditableBase;                       // composes the aliased trait

    function f() { $x = 1; return $x; }      // any method with a non-empty body
}

Run:

CBM_LSP_DISABLED=1 codebase-memory-mcp cli index_repository \
  '{"repo_path":"/path/to/that/dir","mode":"fast"}'

→ RSS climbs to ~18–20 GB and the process is killed (exit 137). Vendor\Pkg\Auditable does not need to exist — it is an unresolved, pure short-name collision.

All three ingredients are required. Removing any one makes it index instantly at ~0 GB (verified, each run monitored for peak RSS):

Change from the repro above Result
rename the trait so its name ≠ Auditable ✅ OK, ~0 GB
drop use AuditableBase; (import present but not composed) ✅ OK, ~0 GB
empty method body {} (or no method at all) ✅ OK, ~0 GB
all three present (as above) ❌ OOM, ~20 GB, exit 137

Note: $this is not required — a body of just $x = 1; is enough.

Real-world origin: this is the shape of a trait that wraps the popular owen-it/laravel-auditing package, e.g. use OwenIt\Auditing\Auditable as AuditableBase; inside a local trait Auditable. So it hits real Laravel apps, not just synthetic input.

Logs

From the minimal single-file repro above — it dies right at the start of the definitions pass:

level=info msg=mem.init budget_mb=18432 total_ram_mb=36864
level=info msg=pipeline.discover files=1 elapsed_ms=0
level=info msg=pipeline.route path=full
level=info msg=pass.start pass=structure files=1
level=info msg=pass.done pass=structure nodes=2 edges=1
level=info msg=pass.timing pass=structure elapsed_ms=0
level=info msg=pipeline.mode mode=sequential files=1
level=info msg=pkgmap.scan_repo manifests=0
level=info msg=pkgmap.scan manifests_from_files=0 manifests_from_walk=0 entries=0
level=info msg=pass.start pass=definitions files=1
<no further output — SIGKILL / OOM, exit 137>

Anything else?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.stability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions