Skip to content

editor: Fix crash when copying and pasting using multiple cursors - #61545

Merged
ChristopherBiscardi merged 2 commits into
zed-industries:mainfrom
timvermeulen:fix-multicursor-copy-paste-crash
Jul 24, 2026
Merged

editor: Fix crash when copying and pasting using multiple cursors#61545
ChristopherBiscardi merged 2 commits into
zed-industries:mainfrom
timvermeulen:fix-multicursor-copy-paste-crash

Conversation

@timvermeulen

Copy link
Copy Markdown
Collaborator

Fixes a crash when copying and pasting a mixed empty/nonempty multi-cursor selection.

Editor::do_copy is meant to insert a newline after each non-final selection that doesn't copy the entire line, but prev_selection_was_entire_line is currently based on the current selection instead of the previous one. Editor::cut_common does already correctly track this state across loop iterations.

This can lead to an out of bounds crash when pasting because the indexing logic in Editor::do_paste relies on these newlines being added correctly, depending on is_entire_line.

Repro:

foo
bar
  1. select foo
  2. option-click after bar to add an empty selection
«fooˇ»
barˇ
  1. copy
  2. paste

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content adheres to Zed's UI standards (UX/UI and icon guidelines)
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • Fixed a crash when copying and pasting using multiple cursors.

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jul 23, 2026
@zed-community-bot zed-community-bot Bot added community champion Issues filed by our amazing community champions! 🫶 guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions labels Jul 23, 2026

@ChristopherBiscardi ChristopherBiscardi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This definitely fixes a crash, thanks!

crash log
thread 'main' (57198292) panicked at crates/editor/src/clipboard.rs:110:56:
end byte index 8 is out of bounds of `foobar
`
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
   1: core::panicking::panic_fmt
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14
   2: core::str::slice_error_fail_rt
   3: core::str::slice_error_fail
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/str/mod.rs:69:5
   4: <core::ops::range::Range<usize> as core::slice::index::SliceIndex<str>>::index
             at /Users/chris/.rustup/toolchains/1.95.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/str/traits.rs:241:21
   5: <str as core::ops::index::Index<core::ops::range::Range<usize>>>::index
             at /Users/chris/.rustup/toolchains/1.95.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/str/traits.rs:63:15
   6: <editor::Editor>::do_paste::{closure#0}::{closure#2}
             at ./crates/editor/src/clipboard.rs:110:56
   7: <gpui::app::App as gpui::AppContext>::update_entity::<multi_buffer::MultiBuffer, (), <editor::Editor>::do_paste::{closure#0}::{closure#2}>::{closure#0}
             at ./crates/gpui/src/app.rs:2642:26
   8: <gpui::app::App>::update::<(), <gpui::app::App as gpui::AppContext>::update_entity<multi_buffer::MultiBuffer, (), <editor::Editor>::do_paste::{closure#0}::{closure#2}>::{closure#0}>
             at ./crates/gpui/src/app.rs:1031:22
   9: <gpui::app::App as gpui::AppContext>::update_entity::<multi_buffer::MultiBuffer, (), <editor::Editor>::do_paste::{closure#0}::{closure#2}>
             at ./crates/gpui/src/app.rs:2640:14
  10: <gpui::app::context::Context<editor::Editor> as gpui::AppContext>::update_entity::<multi_buffer::MultiBuffer, (), <editor::Editor>::do_paste::{closure#0}::{closure#2}>
             at ./crates/gpui/src/app/context.rs:808:18
  11: <gpui::app::entity_map::Entity<multi_buffer::MultiBuffer>>::update::<(), gpui::app::context::Context<editor::Editor>, <editor::Editor>::do_paste::{closure#0}::{closure#2}>
             at ./crates/gpui/src/app/entity_map.rs:481:12
  12: <editor::Editor>::do_paste::{closure#0}
             at ./crates/editor/src/clipboard.rs:95:29
  13: <editor::Editor>::transact::<<editor::Editor>::do_paste::{closure#0}>::{closure#0}
             at ./crates/editor/src/editor.rs:8346:13
  14: <editor::Editor>::with_selection_effects_deferred::<core::option::Option<clock::Lamport>, <editor::Editor>::transact<<editor::Editor>::do_paste::{closure#0}>::{closure#0}>
             at ./crates/editor/src/selection.rs:102:22
  15: <editor::Editor>::transact::<<editor::Editor>::do_paste::{closure#0}>
             at ./crates/editor/src/editor.rs:8344:14
  16: <editor::Editor>::do_paste
             at ./crates/editor/src/clipboard.rs:76:14
  17: <editor::Editor>::paste_item
             at ./crates/editor/src/clipboard.rs:329:44
  18: <editor::Editor>::paste
             at ./crates/editor/src/clipboard.rs:254:18
  19: <<editor::Editor>::paste as core::ops::function::Fn<(&mut editor::Editor, &editor::actions::Paste, &mut gpui::window::Window, &mut gpui::app::context::Context<editor::Editor>)>>::call
             at /Users/chris/.rustup/toolchains/1.95.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:79:5
  20: editor::element::register_action::<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}::{closure#0}
             at ./crates/editor/src/element.rs:10641:17
  21: <gpui::app::App as gpui::AppContext>::update_entity::<editor::Editor, (), editor::element::register_action<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}::{closure#0}>::{closure#0}
             at ./crates/gpui/src/app.rs:2642:26
  22: <gpui::app::App>::update::<(), <gpui::app::App as gpui::AppContext>::update_entity<editor::Editor, (), editor::element::register_action<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}::{closure#0}>::{closure#0}>
             at ./crates/gpui/src/app.rs:1031:22
  23: <gpui::app::App as gpui::AppContext>::update_entity::<editor::Editor, (), editor::element::register_action<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}::{closure#0}>
             at ./crates/gpui/src/app.rs:2640:14
  24: <gpui::app::entity_map::Entity<editor::Editor>>::update::<(), gpui::app::App, editor::element::register_action<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}::{closure#0}>
             at ./crates/gpui/src/app/entity_map.rs:481:12
  25: editor::element::register_action::<editor::actions::Paste, <editor::Editor>::paste>::{closure#0}
             at ./crates/editor/src/element.rs:10640:20
  26: <gpui::window::Window>::dispatch_action_on_node_inner
             at ./crates/gpui/src/window.rs:5391:21
  27: <gpui::window::Window>::dispatch_action_on_node
             at ./crates/gpui/src/window.rs:5311:14
  28: <gpui::window::Window>::dispatch_key_event
             at ./crates/gpui/src/window.rs:5146:22
  29: <gpui::window::Window>::dispatch_event
             at ./crates/gpui/src/window.rs:4919:18
  30: <gpui::window::Window>::new::{closure#17}::{closure#0}
             at ./crates/gpui/src/window.rs:1738:61
  31: <gpui::app::App>::update_window_id::<gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>::{closure#0}
             at ./crates/gpui/src/app.rs:1782:26
  32: <gpui::app::App>::update::<core::option::Option<gpui::window::DispatchEventResult>, <gpui::app::App>::update_window_id<gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>::{closure#0}>
             at ./crates/gpui/src/app.rs:1031:22
  33: <gpui::app::App>::update_window_id::<gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>
             at ./crates/gpui/src/app.rs:1776:14
  34: <gpui::app::App as gpui::AppContext>::update_window::<gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>
             at ./crates/gpui/src/app.rs:2670:14
  35: <gpui::app::async_context::AsyncApp as gpui::AppContext>::update_window::<gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>
             at ./crates/gpui/src/app/async_context.rs:94:14
  36: <gpui::window::AnyWindowHandle>::update::<gpui::app::async_context::AsyncApp, gpui::window::DispatchEventResult, <gpui::window::Window>::new::{closure#17}::{closure#0}>
             at ./crates/gpui/src/window.rs:6310:12
  37: <gpui::window::Window>::new::{closure#17}
             at ./crates/gpui/src/window.rs:1738:22
  38: <alloc::boxed::Box<dyn core::ops::function::FnMut<(gpui::interactive::PlatformInput,), Output = gpui::window::DispatchEventResult>> as core::ops::function::FnMut<(gpui::interactive::PlatformInput,)>>::call_mut
             at /Users/chris/.rustup/toolchains/1.95.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2247:9
  39: gpui_macos::window::handle_key_event::{closure#0}
             at ./crates/gpui_macos/src/window.rs:2135:14
  40: gpui_macos::window::handle_key_event
             at ./crates/gpui_macos/src/window.rs:2221:27
  41: gpui_macos::window::handle_key_equivalent
             at ./crates/gpui_macos/src/window.rs:2046:5
  42: <unknown>
  43: <unknown>
  44: <unknown>
  45: <unknown>
  46: <unknown>
  47: <unknown>
  48: <unknown>
  49: <() as objc::message::MessageArguments>::invoke::<()>
             at /Users/chris/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc-0.2.7/src/message/mod.rs:128:17
  50: objc::message::platform::send_unverified::<objc::runtime::Object, (), ()>
             at /Users/chris/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc-0.2.7/src/message/apple/mod.rs:27:9
  51: objc::message::send_message::<objc::runtime::Object, (), ()>
             at /Users/chris/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc-0.2.7/src/message/mod.rs:178:5
  52: <*mut objc::runtime::Object as cocoa::appkit::NSApplication>::run
             at /Users/chris/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cocoa-0.26.0/src/appkit.rs:628:9
  53: <gpui_macos::platform::MacPlatform as gpui::platform::Platform>::run
             at ./crates/gpui_macos/src/platform.rs:511:17
  54: <gpui::app::Application>::run::<zed::main::{closure#12}>
             at ./crates/gpui/src/app.rs:231:18
  55: zed::main
             at ./crates/zed/src/main.rs:478:9
  56: <fn() as core::ops::function::FnOnce<()>>::call_once
             at /Users/chris/.rustup/toolchains/1.95.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@ChristopherBiscardi ChristopherBiscardi self-assigned this Jul 24, 2026
@ChristopherBiscardi ChristopherBiscardi added the area:editor Feedback for code editing, formatting, editor iterations, etc label Jul 24, 2026
@ChristopherBiscardi
ChristopherBiscardi added this pull request to the merge queue Jul 24, 2026
Merged via the queue into zed-industries:main with commit e12992c Jul 24, 2026
72 checks passed
mdz-axo added a commit to mdz-axo/zed-kask that referenced this pull request Jul 25, 2026
Upstream changes (zed-industries/zed main, 27 commits):
- agent: Add agent.compaction_model setting for context compaction (zed-industries#60012)
- agent: Show effort selector for anthropic compatible providers (zed-industries#61579)
- acp: Update agent-client-protocol SDK to 2.0.0 (zed-industries#61570)
- client: Extract proxy handshakes into new proxy_handshake crate (zed-industries#61427)
- collab: Fix multiworkspace location out of sync bugs (zed-industries#61598)
- editor: Fix sticky header drag cancels autoscroll (zed-industries#53592)
- editor: Fix crash when copying and pasting using multiple cursors (zed-industries#61545)
- editor: Skip untitled buffers when saving a multi-buffer (zed-industries#61380)
- gpui: Fix images not being drawn with rounded corners with ObjectFit::Cover (zed-industries#61383)
- gpui: Fix deadlock in performance profiler and reenable it (zed-industries#61584)
- git_ui: Prevent Git panel bindings in repository selector (zed-industries#61282)
- language_model: Add explicit OpenAI conversation compaction and fix Anthropic compaction (zed-industries#61370)
- markdown: Fix squashed Mermaid diagrams in markdown preview (zed-industries#61260)
- Opus 5 BYOK Support (zed-industries#61596)
- repl: Show add-cell controls in empty notebooks (zed-industries#61329)
- search: Escape seeded buffer search query in regex mode (zed-industries#57748)
- settings: Fix VS Code import appending duplicate file associations (zed-industries#61355)
- settings: Split VSCode and Zed keymap files (zed-industries#61532)
- Treat blank spawn_agent session IDs as absent (zed-industries#60893)
- worktree: Reload git state when a watcher rescan covers a repository (zed-industries#61541)
- Plus 7 more minor fixes.

Merge fixes:
- crates/agent/src/thread.rs: replay_tool_call used 'message_ix' (undefined)
  after auto-merge; renamed to 'owning_message_ix' (the parameter name).
- Cargo.toml: Removed stale workspace members hkask-wallet and hkask-git-cas
  (both directories deleted in prior commits but workspace entries remained).
- kask/crates/hkask-regulation/src/wallet_manager.rs: Stubbed consume() and
  settle_rjoules() on WalletBudgetPort — these were API-key encumbrance
  operations from the deleted hkask-wallet crate; regulation tracks per-agent
  gas balances, not per-key encumbrances.
- kask/crates/hkask-regulation/src/wallet_gas_calibrator.rs: Fixed test to
  use crate::agent_wallet_store::WalletStore instead of hkask_storage::WalletStore.
- kask/crates/hkask-regulation/Cargo.toml: Added tokio macros feature to
  dev-dependencies for #[tokio::test].
- kask/crates/kask_bridge/Cargo.toml: Added futures dependency (needed by
  context_injector.rs for futures::executor::block_on).
- kask/crates/kask_bridge/src/context_injector.rs: Fixed futures_util::executor
  to futures::executor (futures-util doesn't include executor module).

Release Notes:

- N/A
jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
…d-industries#61545)

Fixes a crash when copying and pasting a mixed empty/nonempty
multi-cursor selection.

`Editor::do_copy` is meant to insert a newline after each non-final
selection that doesn't copy the entire line, but
`prev_selection_was_entire_line` is currently based on the current
selection instead of the previous one. `Editor::cut_common` does already
correctly track this state across loop iterations.

This can lead to an out of bounds crash when pasting because the
indexing logic in `Editor::do_paste` relies on these newlines being
added correctly, depending on `is_entire_line`.

Repro:

```
foo
bar
```
1. select `foo`
2. option-click after `bar` to add an empty selection
```
«fooˇ»
barˇ
```
3. copy
4. paste

## 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 copying and pasting using multiple cursors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:editor Feedback for code editing, formatting, editor iterations, etc cla-signed The user has signed the Contributor License Agreement community champion Issues filed by our amazing community champions! 🫶 guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants