-
Notifications
You must be signed in to change notification settings - Fork 179
Description
Describe the bug
When fuzzy matching is on, and you have files starting with multibyte chars, and you type some letters and hit tab, you can trigger a panic.
This is related to a number of existing issues but I think I found a distinct case.
nushell/nushell#15302
nushell/nushell#13951
nushell/nushell#12680
nushell/nushell#11916
The bug is in the reedline crate, which I had a look at, but I'm putting the issue here as I think this where most of the issues are logged.
There were a couple of recent PRs that fixed some of these unicode issues -
#903
#886
But they don't fix this one, it still panics.
How to reproduce
You need fuzzy completions enabled in config.nu
:
$env.config.completions.algorithm = "fuzzy"
And then do this
mkdir testdir
cd testdir
touch "abcdef"
touch "验abcdef"
ls ac<tab>
You get the following, or maybe it just drops out of completion, sometimes the panic message is suppressed.
x Main thread panicked.
|-> at ~\reedline\src\menu\columnar_menu.rs:318:46
`-> byte index 2 is not a char boundary; it is inside '验' (bytes 0..3) of `验abcdef`
Note that ab<tab>
will not crash, only ac<tab>
This is because ab
is a substring of the filename, but ac
is not, and only produces matches in fuzzy mode.
It happens because in reedline/src/menu/columnar_menu.rs:311 (fn create_string)
it tries to search for an exact substring to underline, but in this case it finds nothing, so match_position defaults to 0.
let match_position = suggestion
.value
.to_lowercase()
.find(&shortest_base.to_lowercase())
.unwrap_or(0);
When the next line tries to slice the match result, it's assuming that we found the substring. If we did, then match_len would be the correct byte length and the slice would work properly.
In this case though it tries to slice 2 bytes from position 0 (we typed ac
so that's length 2) but the first character of our file is 验
which is actually 3 bytes long, so the slice is mid-char and panics.
let match_str = &suggestion.value[match_position
..match_position + match_len.min(suggestion.value.len() - match_position)];
Expected behavior
Don't panic
Configuration
I built a recent version to check it was still happening
key | value |
---|---|
version | 0.105.1 |
major | 0 |
minor | 105 |
patch | 1 |
branch | main |
commit_hash | 1fe62ee6132372453d6bfeb95978ee61a2b77f3b |
build_os | windows-x86_64 |
build_target | x86_64-pc-windows-msvc |
rust_version | rustc 1.85.1 (4eb161250 2025-03-15) |
rust_channel | 1.85.1-x86_64-pc-windows-msvc |
cargo_version | cargo 1.85.1 (d73d2caf9 2024-12-31) |
build_time | 2025-06-11 06:54:27 +10:00 |
build_rust_channel | debug |
allocator | standard |
features | default, sqlite, trash |
installed_plugins |