# editor: Fix crash when a row highlight's anchors are reversed \(\#64604\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/a982949071beaa4ad5464bf7f9a8e7db66400e95)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: a982949071beaa4ad5464bf7f9a8e7db66400e95

Requested commit: a982949071beaa4ad5464bf7f9a8e7db66400e95

Commit: a982949071beaa4ad5464bf7f9a8e7db66400e95

Tree: d89e426a617691c84ff21ab41fd6ef07d81785dd

Author: Agus Zubiaga

Committer: GitHub

## Message

```
editor: Fix crash when a row highlight's anchors are reversed (#64604)

# Objective

Fixes ZED-BJQ (`slice index starts at N but ends at N-1` in
`Editor::highlighted_display_rows_in_range`).

Since #63395, rendering only looks at the row highlights that intersect
the viewport, found with two binary searches over the stored ranges. If
a stored range has `start > end`, the two searches can cross and we
panic.

That happens with merge conflicts where one side is empty (one branch
deleted the block). The conflict parser built every side as
`anchor_after(start)..anchor_before(end)`, so an empty side became a
zero-width range whose start sorts after its end. When you type your
resolution at that spot, the start anchor moves past the new text while
the end stays put, and until the conflict set re-parses the highlight is
inside out. If the viewport lands inside the typed text on that frame,
Zed crashes.

## Solution

We now search for the start index only within the prefix that ends at
the end index, so an inverted range can never produce an inverted slice;
the existing per-highlight filter drops it. The parser also emits empty
sides as `anchor_before..anchor_after`, so they stay ordered and grow
around text typed into them, which also means the typed lines get the
"ours"/"theirs" color immediately instead of after the re-parse.

## Testing

- `test_row_highlights_for_empty_conflict_side_after_edit` parses an
empty-side conflict, stores its highlight plus a hand-built inside-out
range, types into the empty side, and renders every viewport. It panics
without the editor change.
- `test_parse_conflicts_with_empty_sides` checks the parser emits
ordered ranges for empty sides and that typed text lands inside them.
- To reproduce manually on `main`: open a file with a conflict whose
`ours` side is empty, put the cursor at the start of the `=======` line,
paste more lines than fit on screen, then scroll so only the pasted text
is visible before the conflict re-parses (easiest with a nonzero
`git.gutter_debounce`).

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed a crash when typing into an empty side of a merge conflict.
```

## Parents

- [18ad8d11958cba96af95dae5ef4b14a972f6b650](https://git.cafe/gitcafe/zed/commit/18ad8d11958cba96af95dae5ef4b14a972f6b650?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/a982949071beaa4ad5464bf7f9a8e7db66400e95?format=markdown)
