Skip to content

fix(goto): stop slicing strings off char boundaries, which killed the server - #237

Merged
mmsaki merged 1 commit into
asyncswap:mainfrom
rifuki:fix/goto-panics-on-non-ascii
Sep 15, 2026
Merged

mmsaki merged 1 commit into
asyncswap:mainfrom
rifuki:fix/goto-panics-on-non-ascii

Conversation

@rifuki

@rifuki rifuki commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #236.

A panic in these two spots doesn't fail the request — it exits the process, so the project index is lost and the editor has no language server until it's restarted. That's why I'd put this ahead of my other open PRs.

validate_goto_target sliced the target line by LSP columns with only a byte-length check on end_col. start_col was never checked, so an inverted range panicked too, and on a line with multi-byte text either column can land mid-character. goto_declaration_by_name sliced the file read fresh from disk using offsets from an earlier solc build, which can be stale as well as mid-character.

Both functions are already best-effort and have give-up branches — continue for an unparseable src, "can't read target, assume valid" for an unreadable file. Switching from indexing to str::get just routes an unusable range into those.

Worth being clear about what this does and doesn't do: it stops the crash. The underlying mismatch — LSP columns are character offsets while these slices are by byte — is #234 and isn't fixed here. On a non-ASCII line validate_goto_target now declines to judge instead of answering wrongly, which is what it already does when it can't read the file at all.

Three tests, each of which panics on main:

  • a column landing inside a multi-byte character
  • an inverted range, which the byte bound never rejected
  • a stale build offset landing mid-character in the on-disk file

I ran them against main first to confirm the exact panic (start byte index 8 is not a char boundary; it is inside '状') rather than assuming. There's also an ASCII case asserting the matching behavior is unchanged.

cargo test 663 passed, clippy and fmt clean.

Independent of my other open PRs — this one only touches goto.rs.

… server

Go-to-definition on a file containing non-ASCII text could panic, and a panic
here takes the whole process down — the project index goes with it and the
editor has no language server until it is restarted.

    thread 'main' panicked at src/goto.rs:1334:26:
    start byte index 8 is not a char boundary; it is inside '状'

Two sites slice by offsets that are not guaranteed to sit on a boundary.

`validate_goto_target` slices the target line by LSP columns, guarded only by
a byte-length check on `end_col`. `start_col` was never checked at all, so an
inverted range panicked too, and on a line with multi-byte text either column
can land mid-character.

`goto_declaration_by_name` slices the file read fresh from disk using offsets
that came from an earlier solc build, so they can be stale as well as
mid-character.

Both functions are already best-effort and have give-up branches — `continue`
for an unparseable `src`, and "can't read target, assume valid" for an
unreadable file. An unusable range now takes those branches instead of
panicking, via `str::get` rather than indexing.

This is about not crashing. The underlying mismatch — LSP columns are
character offsets while these slices are by byte — is asyncswap#234 and is not fixed
here; `validate_goto_target` on a non-ASCII line now declines to judge rather
than answering wrongly, which is the same thing it already does when it cannot
read the file.

Three tests, all of which panic on main:
- a column landing inside a multi-byte character
- an inverted range, which the byte bound never rejected
- a stale build offset landing mid-character in the on-disk file

Plus an ASCII case asserting the matching behavior is unchanged.

Closes asyncswap#236.
@rifuki
rifuki force-pushed the fix/goto-panics-on-non-ascii branch from c877672 to adcd134 Compare August 25, 2026 18:22
@mmsaki
mmsaki merged commit 804f2e9 into asyncswap:main Sep 15, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go-to-definition panics and kills the server process on files with non-ASCII text

2 participants