bread-launcher: fix UTF-8 panic in whole-word matching
matches_term advanced its scan with start = i + 1 — one byte past the START
of a failed match rather than past the whole match. Both i and i + tlen are
guaranteed char boundaries; i + 1 is not, so a multi-byte term that failed
the word-boundary check left start inside a character and the following
field[start..] slice panicked.
matches_term("café", "é") reproduces it: byte index 4 is not a char
boundary. The path is reached from priority_rank over real .desktop Name=
values, so any non-ASCII application name could crash the launcher's sort —
never hit locally because every installed app here happens to be ASCII.
This commit is contained in:
parent
801df1e85e
commit
3326207d34
1 changed files with 24 additions and 1 deletions
|
|
@ -71,7 +71,15 @@ pub fn matches_term(field: &str, term: &str) -> bool {
|
|||
if before_ok && after_ok {
|
||||
return true;
|
||||
}
|
||||
start = i + 1;
|
||||
// Advance past the WHOLE match, not one byte past its start. Both `i`
|
||||
// (a match start) and `i + tlen` (its end) are guaranteed char
|
||||
// boundaries; `i + 1` is not, so a multi-byte term that failed the
|
||||
// word-boundary check left `start` inside a character and the next
|
||||
// `field[start..]` slice panicked outright. `matches_term("café", "é")`
|
||||
// reproduced it: "byte index 4 is not a char boundary". Reached via
|
||||
// priority_rank over real .desktop `Name=` values, so any non-ASCII
|
||||
// app name could crash the launcher's sort.
|
||||
start = i + tlen;
|
||||
if start >= field.len() {
|
||||
break;
|
||||
}
|
||||
|
|
@ -167,6 +175,21 @@ pub fn split_sections(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn multibyte_term_that_fails_word_boundary_does_not_panic() {
|
||||
// "é" occurs in "café" but is preceded by an alphanumeric, so the
|
||||
// whole-word check fails and the scan must continue — landing mid
|
||||
// character before the fix.
|
||||
assert!(!super::matches_term("café", "é"));
|
||||
assert!(!super::matches_term("naïve café", "ï"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multibyte_whole_word_still_matches() {
|
||||
assert!(super::matches_term("café bar", "café"));
|
||||
assert!(super::matches_term("día", "día"));
|
||||
}
|
||||
|
||||
use super::*;
|
||||
|
||||
fn entry(name: &str, wm_class: Option<&str>) -> DesktopEntry {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue