Skip to content

lash lint panics when a long note has a multi-byte char at the truncation boundary #70

Description

@fohara

Hit this on lash 0.4.0 while linting fixture-site: lash lint crashes with exit 101 instead of reporting its findings.

ERROR Panic occurred location=crates/lash-types/src/task.rs:222:40 end byte index 57 is not a char boundary; it is inside '—' (bytes 55..58 of string)

The trigger is a contextual note that is long enough for W_NOTE_TOO_LONG (over 200 chars) and happens to have a multi-byte character straddling byte 57. Rendering the warning calls ContextualNote::truncated_text(60), which slices by bytes:

format!("{}...", &self.text[..max_len - 3])

&self.text[..57] panics whenever byte 57 falls inside a multi-byte char. An em dash at bytes 55..58 does it, so does any accented letter or CJK char at that position.

Minimal repro, two files in an empty directory:

lash.index.md

# Index

- [Repro](tasks.repro.md)

tasks.repro.md (the note is 55 a's, an em dash, then enough padding to pass 200 chars)

# Repro

@id: repro

## Tasks

- [ ] a task

## Implementation notes

- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa— trailing text bbbb…(pad past 200 chars)…bbbb

Then lash index && lash lint crashes with the panic above.

Fix is to truncate on a char boundary, floor_char_boundary once it stabilizes, or walk back with is_char_boundary, or take chars instead of bytes. Worth a quick audit for other byte-index slicing on user text while in there, any truncation helper has the same exposure.

In any case, the workaround is easy once you spot it (reword the note so no multi-byte char sits at byte 55..58), it just presents as lint crashing on a file that looks fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions