Prevent out of bounds access in recursive_score_match
(#35630)
Closes https://github.com/zed-industries/zed/issues/33668 The recursive case increments both indices by 1, but only one of the two had a base case check in the function prologue so the other could spill over into a different matrix row or out of bounds entirely. Lacking a test as I haven't figured out a test case yet. Release Notes: - Fixed out of bounds panic in fuzzy matching
This commit is contained in:
parent
c59c436a11
commit
69794db331
1 changed files with 19 additions and 18 deletions
|
@ -208,8 +208,15 @@ impl<'a> Matcher<'a> {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path_len = prefix.len() + path.len();
|
let limit = self.last_positions[query_idx];
|
||||||
|
let max_valid_index = (prefix.len() + path_lowercased.len()).saturating_sub(1);
|
||||||
|
let safe_limit = limit.min(max_valid_index);
|
||||||
|
|
||||||
|
if path_idx > safe_limit {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path_len = prefix.len() + path.len();
|
||||||
if let Some(memoized) = self.score_matrix[query_idx * path_len + path_idx] {
|
if let Some(memoized) = self.score_matrix[query_idx * path_len + path_idx] {
|
||||||
return memoized;
|
return memoized;
|
||||||
}
|
}
|
||||||
|
@ -218,16 +225,13 @@ impl<'a> Matcher<'a> {
|
||||||
let mut best_position = 0;
|
let mut best_position = 0;
|
||||||
|
|
||||||
let query_char = self.lowercase_query[query_idx];
|
let query_char = self.lowercase_query[query_idx];
|
||||||
let limit = self.last_positions[query_idx];
|
|
||||||
|
|
||||||
let max_valid_index = (prefix.len() + path_lowercased.len()).saturating_sub(1);
|
|
||||||
let safe_limit = limit.min(max_valid_index);
|
|
||||||
|
|
||||||
let mut last_slash = 0;
|
let mut last_slash = 0;
|
||||||
|
|
||||||
for j in path_idx..=safe_limit {
|
for j in path_idx..=safe_limit {
|
||||||
let extra_lowercase_chars_count = extra_lowercase_chars
|
let extra_lowercase_chars_count = extra_lowercase_chars
|
||||||
.iter()
|
.iter()
|
||||||
.take_while(|(i, _)| i < &&j)
|
.take_while(|&(&i, _)| i < j)
|
||||||
.map(|(_, increment)| increment)
|
.map(|(_, increment)| increment)
|
||||||
.sum::<usize>();
|
.sum::<usize>();
|
||||||
let j_regular = j - extra_lowercase_chars_count;
|
let j_regular = j - extra_lowercase_chars_count;
|
||||||
|
@ -236,10 +240,9 @@ impl<'a> Matcher<'a> {
|
||||||
lowercase_prefix[j]
|
lowercase_prefix[j]
|
||||||
} else {
|
} else {
|
||||||
let path_index = j - prefix.len();
|
let path_index = j - prefix.len();
|
||||||
if path_index < path_lowercased.len() {
|
match path_lowercased.get(path_index) {
|
||||||
path_lowercased[path_index]
|
Some(&char) => char,
|
||||||
} else {
|
None => continue,
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let is_path_sep = path_char == MAIN_SEPARATOR;
|
let is_path_sep = path_char == MAIN_SEPARATOR;
|
||||||
|
@ -255,18 +258,16 @@ impl<'a> Matcher<'a> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let need_to_score = query_char == path_char || (is_path_sep && query_char == '_');
|
let need_to_score = query_char == path_char || (is_path_sep && query_char == '_');
|
||||||
if need_to_score {
|
if need_to_score {
|
||||||
let curr = if j_regular < prefix.len() {
|
let curr = match prefix.get(j_regular) {
|
||||||
prefix[j_regular]
|
Some(&curr) => curr,
|
||||||
} else {
|
None => path[j_regular - prefix.len()],
|
||||||
path[j_regular - prefix.len()]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut char_score = 1.0;
|
let mut char_score = 1.0;
|
||||||
if j > path_idx {
|
if j > path_idx {
|
||||||
let last = if j_regular - 1 < prefix.len() {
|
let last = match prefix.get(j_regular - 1) {
|
||||||
prefix[j_regular - 1]
|
Some(&last) => last,
|
||||||
} else {
|
None => path[j_regular - 1 - prefix.len()],
|
||||||
path[j_regular - 1 - prefix.len()]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if last == MAIN_SEPARATOR {
|
if last == MAIN_SEPARATOR {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue