Skip to content

C/C++: a CRLF file with a backslash-continued string literal swallows the rest of the file, and every later function is missing from the graph #1546

Open

Description

@noohi

Version

codebase-memory-mcp 0.10.1

Platform

Windows (x64)

Install channel

GitHub release archive / install.sh / install.ps1

Binary variant

standard

What happened, and what did you expect?

When a C/C++ source file uses CRLF line endings and contains a string literal continued
with a backslash at end of line, the extractor loses the end of that literal. The
enclosing function is emitted as a single node spanning to end of file, and every
function defined after it is missing from the graph entirely.

The same file with LF line endings extracts correctly. Line endings are the only
difference between the two inputs below.

Expected: the same set of functions, with the same spans, regardless of line endings.
CRLF is the default checkout on Windows, so this affects a normally configured Windows
working tree.

Both conditions are required. CRLF alone is fine, and backslash continuation on LF is
fine. Backslash continuation is uncommon in modern C++, since adjacent string literal
concatenation is the usual idiom, which is probably why this has survived several
releases.

Reproduction

1. Code. Two directories, byte-identical apart from line endings. Because the bug is
byte-sensitive, here is a generator rather than a paste, so the exact bytes survive
copying (176 bytes LF, 196 bytes CRLF):

src = r'''void Head()
{
    int h = 0;
}

void Middle()
{
    const wchar_t* s = L"line 0\r\n\
line 1\r\n";
}

void TrailerOne()
{
    int a = 1;
}

void TrailerTwo()
{
    int b = 2;
}
'''
import os
for name, text in (('lf', src), ('crlf', src.replace('\n', '\r\n'))):
    os.makedirs(name, exist_ok=True)
    open(os.path.join(name, 'repro.cpp'), 'wb').write(text.encode())

2. Commands. Index each directory and list the functions:

codebase-memory-mcp cli index_repository '{"repo_path":"<dir>"}'
codebase-memory-mcp cli query_graph '{"project":"<name>","query":"MATCH (n:Function) RETURN n.name, n.start_line, n.end_line"}'

3. Result vs expected.

Line endings Head Middle TrailerOne TrailerTwo
LF (expected) 1-4 6-10 12-15 17-20
CRLF (actual) 1-4 6-20 missing missing

Middle absorbs the remaining 10 lines of the file, and the two functions defined after
it are absent from the graph. The whole-graph counts differ accordingly: LF indexes to 8
nodes / 7 edges, CRLF to 6 nodes / 5 edges. CBM_LSP_DISABLED=1 does not change the
outcome, so this looks like the base extractor rather than the Hybrid LSP layer.

One caveat when reproducing: index into a fresh cache directory. An incremental re-index
of an already-indexed project returns parse_partial_count: 0 even though the graph is
still missing the functions, which makes the flag look like it cleared when it has not.

Logs

On 0.10.1, `index_repository` on the CRLF directory reports `parse_partial_count: 1`,
and the per-project logfile carries:


parse_partial	8-12,12-12,20-20	repro.cpp


Releases before 0.10.0 reported this file clean, so the loss was fully silent. Since
0.10.0 the flag is raised, but the file is still not extracted.

Diagnostics trajectory (memory / performance / leak issues)


Project scale (if relevant)

No response

Confirmations

  • I searched existing issues and this is not a duplicate.
  • My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.

Activity

  1. added
    language-requestRequest for new language support
    parsing/qualityGraph extraction bugs, false positives, missing edges
    windowsWindows-specific issues
    on Aug 11, 2026
  2. DeusData commented on Aug 12, 2026

    @DeusData
    Owner

    Thanks @noohi — this reproduces exactly as written, and the generator-not-a-paste was the right call for a byte-sensitive bug.

    Current read: the C/C++ grammars we use are vendored generated parsers, so the line-splice handling that mishandles \\ + CRLF lives either in the grammar itself or needs a normalization layer ahead of it. Normalizing \\r\\n before parsing is the obvious candidate, but it shifts byte offsets, so it has to be done with the span mapping in mind rather than as a blind substitution — which is why we're not rushing it into today's release.

    Queued for the next batch with that analysis attached. Your caveat about indexing into a fresh cache is noted too; an incremental re-index reporting parse_partial_count: 0 over a graph that is missing functions is arguably its own reporting bug.

  3. added
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    on Aug 12, 2026
  4. DeusData commented on Sep 26, 2026

    @DeusData
    Owner

    Thank you, @noohi, for the byte-exact generator. It's exactly what a line-ending bug needs!

    I re-ran it (CRLF verified, with the backslash-continued literal) on current main and on the v0.11.0 release. Both copies now produce the same four functions with the same spans: Head, Middle, TrailerOne and TrailerTwo. I tested on macOS; the bug should be byte-level rather than OS-level, but could you re-run your two directories on Windows with v0.11.0 into a fresh cache? If the CRLF copy matches the LF copy for you too, we'll close this. If it doesn't, the platform difference is itself the next lead.

  5. added
    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then close
    on Sep 26, 2026
  6. noohi commented on Sep 26, 2026

    @noohi
    Author

    Re-ran on Windows with v0.11.0 into a fresh cache: cache dir and daemon lock dirs deleted, daemon stopped before the run.
    The CRLF copy still does not match the LF copy here.

    Environment:

    • Windows 11 Pro 10.0.26300, x64
    • codebase-memory-mcp 0.11.0, windows-amd64 binary, SHA256 7edcd3807ebcfd85ec1968985964080f2589748da2fc3c7ce9261eebab31ff04 (matches the release table)
    • Fixture on a local NTFS disk (my earlier runs were on a network share, so that is ruled out)
    • Release binary only; I have not built current main on Windows

    The fixture is the generator output from the report, re-generated today:

    • crlf/repro.cpp SHA256 57d03ea79302446a0da11fa762d9726412500f9573d94eef5a490ed95287b618
    • lf/repro.cpp SHA256 cdc0442b2345ea6da7b11e81fcdb82cb41fe883859d85d2d49be0aa2546ef141

    Driven via cli --json index_repository --args-file ... then query_graph with MATCH (n:Function) RETURN n.name AS name, n.start_line AS first, n.end_line AS last:

    copy nodes / edges parse_partial functions
    lf 8 / 7 0 Head 1-4, Middle 6-10, TrailerOne 12-15, TrailerTwo 17-20
    crlf 6 / 5 1 Head 1-4, Middle 6-20

    So on Windows, Middle still spans to EOF and both trailers vanish.
    If your CRLF copy on macOS hashes to the same value, the difference is in the Windows build or its file-read path rather than the input.
    If it hashes differently, the bytes changed somewhere before the extractor saw them.
    I can run a diagnostic build or a specific flag if that would narrow it.

  7. github-actions commented on Sep 26, 2026

    @github-actions

    Thanks for the report! To move this forward we need a bit more so we can reproduce it ourselves:

    • the codebase-memory-mcp --version you're on
    • the exact steps or command you ran
    • a public repo (or a small dummy snippet) that shows the problem — please don't paste proprietary code

    Once that's here we'll pick it straight back up. Heads-up: issues left awaiting-reporter are automatically closed after a few weeks of silence, but a comment reopens the door anytime.

  8. noohi commented on Sep 26, 2026

    @noohi
    Author

    Everything the bot asks for is in the report and in my comment above, but here it is in one place.

    Version: codebase-memory-mcp 0.11.0, the official windows-amd64 release binary (SHA256 7edcd3807ebcfd85ec1968985964080f2589748da2fc3c7ce9261eebab31ff04).

    Public repro: the generator script in the original report, no proprietary code involved.
    It writes two copies of the same 20-line C++ file, lf/repro.cpp and crlf/repro.cpp.
    Expected hashes: crlf 57d03ea79302446a0da11fa762d9726412500f9573d94eef5a490ed95287b618, lf cdc0442b2345ea6da7b11e81fcdb82cb41fe883859d85d2d49be0aa2546ef141.

    Steps on Windows 11 x64, fixture on a local NTFS disk:

    1. Stop the daemon and delete the cache dir and daemon lock dirs, so the index starts fresh.
    2. Run codebase-memory-mcp cli --json index_repository --args-file args.json with {"repo_path": "<dir>\\lf"}, then the same for crlf.
    3. Run codebase-memory-mcp cli --json query_graph --args-file q.json with {"project": "<project from step 2>", "query": "MATCH (n:Function) RETURN n.name AS name, n.start_line AS first, n.end_line AS last"} for each copy.

    Result: the lf copy gives Head, Middle, TrailerOne and TrailerTwo.
    The crlf copy gives only Head and Middle, with Middle spanning lines 6-20 and parse_partial 1.

    This still reproduces on v0.11.0 today, so please keep it open.

  9. removed
    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then close
    on Oct 19, 2026
  10. DeusData commented on Oct 19, 2026

    @DeusData
    Owner

    Thank you, @noohi, for the Windows 0.11.0 retest, matching release hash, and byte-exact fixtures. You already supplied what the bot requested — sorry for the redundant prompt. The Windows failure remains unresolved in this conversation; no further rerun is requested until there is a specific diagnostic or fix to test.

  11. DeusData commented on Oct 25, 2026

    @DeusData
    Owner

    Thank you for the byte-exact Windows retest and release hash. You have already supplied the required evidence; the Windows-specific mismatch needs maintainer investigation before another rerun. Sorry for the delay; this is waiting on maintainer follow-up, and I’ll follow up soon.

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.windowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions