From e1e4c1b7861a97a795f90d8acd0132238f743ddc 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:56:58 +0200
Subject: [PATCH] Avoid panics when normalizing completion label with invalid
ranges (cherry-pick #23712) (#23719)
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 55598336a67129ca22e2cc5a1417e7c53ff16ecf..cfd96f0c76688ba776d756e06b5f020f455811c4 100644
--- a/crates/project/src/lsp_store.rs
+++ b/crates/project/src/lsp_store.rs
@@ -8818,16 +8818,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;