From f10b43651b06b250abd65570b491cfa03d21f206 Mon Sep 17 00:00:00 2001 From: "gcp-cherry-pick-bot[bot]" <98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 17:18:08 +0200 Subject: [PATCH] Avoid panics when normalizing completion label with invalid ranges (cherry-pick #23712) (#23718) Cherry-picked Avoid panics when normalizing completion label with invalid ranges (#23712) Dev builds show panics related to completion label normalization
Panic ``` index out of bounds: the len is 103 but the index is 103 zed::reliability::init_panic_hook::{{closure}}::h78130eff43c84f6f+110375521 std::panicking::rust_panic_with_hook::hfe205f6954b2c97b+87457752 std::panicking::begin_panic_handler::{{closure}}::h6cb44b3a50f28c44+87456967 std::sys::backtrace::__rust_end_short_backtrace::hf1c1f2a92799bb0e+87449337 rust_begin_unwind+87456084 core::panicking::panic_fmt::h3d8fc78294164da7+7033011 core::panicking::panic_bounds_check::h9397cb495d89a72d+7033511 project::lsp_store::ensure_uniform_list_compatible_label::haf80316ce11edd67+72663592 project::lsp_store::populate_labels_for_completions::{{closure}}::hc93c3c540ef7d2d6+72642960 project::lsp_store::LspStore::completions::{{closure}}::{{closure}}::hb4b5432e24432ca8+72336627 async_task::raw::RawTask::run::hf444c3dc07dd583b+68504803 ::run::hbf5a316eb781a10d+50646579 gpui::platform::linux::platform::::run::hc85518d4552fc4cd+50496669 gpui::app::App::run::hca4e2eaf984ca6f6+109905269 zed::main::h849467ac1a6d32c9+110413414 std::sys::backtrace::__rust_begin_short_backtrace::h81b5ee155a7cf505+110835475 std::rt::lang_start::{{closure}}::h48a83f884cfb6865+110834761 std::rt::lang_start_internal::h5e7c81cecd7f0954+87382485 main+110425932 __libc_start_call_main+22789462491720 __libc_start_main_alias_1+22789462491915 _start+10436606 ```
This can only happen when either `label.runs` or `label.filter_range` has a range that's larger than the label text, which is an error. Instead of panicking, log such errors and fall back to last index (which is not really helpful, but still). Release Notes: - N/A Co-authored-by: Kirill Bulatov --- crates/project/src/lsp_store.rs | 53 +++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 5bdee5cb5cb83a06577ad6ca6d330fc3b95ad958..b8f0d90c8cff9f1bc0c351364056a43c8acdf0a7 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -8786,16 +8786,59 @@ fn ensure_uniform_list_compatible_label(label: &mut CodeLabel) { return; } - for (range, _) in &mut label.runs { - range.start = offset_map[range.start]; - range.end = offset_map[range.end]; + let last_index = new_idx; + let mut run_ranges_errors = Vec::new(); + label.runs.retain_mut(|(range, _)| { + match offset_map.get(range.start) { + Some(&start) => range.start = start, + None => { + run_ranges_errors.push(range.clone()); + return false; + } + } + + match offset_map.get(range.end) { + Some(&end) => range.end = end, + None => { + run_ranges_errors.push(range.clone()); + range.end = last_index; + } + } + true + }); + if !run_ranges_errors.is_empty() { + log::error!( + "Completion label has errors in its run ranges: {run_ranges_errors:?}, label text: {}", + label.text + ); } + let mut wrong_filter_range = None; if label.filter_range == (0..label.text.len()) { label.filter_range = 0..new_text.len(); } else { - label.filter_range.start = offset_map[label.filter_range.start]; - label.filter_range.end = offset_map[label.filter_range.end]; + let mut original_filter_range = Some(label.filter_range.clone()); + match offset_map.get(label.filter_range.start) { + Some(&start) => label.filter_range.start = start, + None => { + wrong_filter_range = original_filter_range.take(); + label.filter_range.start = last_index; + } + } + + match offset_map.get(label.filter_range.end) { + Some(&end) => label.filter_range.end = end, + None => { + wrong_filter_range = original_filter_range.take(); + label.filter_range.end = last_index; + } + } + } + if let Some(wrong_filter_range) = wrong_filter_range { + log::error!( + "Completion label has an invalid filter range: {wrong_filter_range:?}, label text: {}", + label.text + ); } label.text = new_text;