Skip to content

lsp: file-identity edge cases — dot segments, path-form UNC, case-insensitive overlay bypass, BOM, id-width overflows #248

Description

@0xGeorgii

Follow-up from the comprehensive review of PR #239 (LSP server). Line numbers reference the PR branch at review time.

Severity: minor (1-4), nit (5-7) — file-identity and path edge cases across the URI/vfs/loader seam. The vfs module docs explicitly delegate canonical identity to the LSP layer ("the LSP layer derives one canonical absolute path per URI"), but several spellings of one file slip through and key separate documents.

  1. Dot segments survive decoding (uri.rs:62): file_uri_to_path only percent-decodes and fixes drive-letter case; /a/../b.inf and /b.inf intern as two documents (stale/duplicate analyses).
  2. Path-form UNC bypasses the remote-authority rejection (uri.rs:55): file:////server/share/x.inf parses with an empty authority and decodes to //server/share/x.inf — a UNC path on Windows, triggering SMB network I/O from a supposedly-local server.
  3. Case-insensitive filesystems (macOS/Windows): mis-cased import bypasses the overlay (loader.rs:34): source says use lib::Math;, file is lib/math.inf — the walk derives <root>/lib/Math.inf, the overlay (interned under the URI spelling) misses on case-sensitive Path equality, but fs::read succeeds on the case-insensitive disk → stale disk text is analyzed, and later edits to the open buffer never invalidate the importing analysis.
  4. No UTF-8 BOM stripping in the disk ingestion path (loader.rs:40): clients strip the BOM from opened buffers, but unopened closure files read via read_to_string keep U+FEFF — every line-0 position is off by one UTF-16 unit versus the client's view, plus a spurious lexer error at file start.
  5. Scheme matching is byte-exact (uri.rs:51): RFC-3986-valid File:///FILE:// and the RFC 8089 single-slash file:/path form are silently rejected.
  6. Bare/malformed drive URIs (uri.rs:119): file:///C:C: and file:///c:nameC:name — drive-RELATIVE paths returned instead of rejection.
  7. Width overflows (robustness nits): LineIndex::new truncates line starts with as u32 for ≥4 GiB texts, breaking partition_point monotonicity (line_index.rs:58); FileId minting wraps at 2^32 interned paths (vfs/lib.rs:89). Explicit failure preferable to silent wrap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglspLanguage Server Protocol

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions