From e1c6be0682b795862d4105da91f7c15b97ceaeb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=C3=A4llberg?= Date: Wed, 20 Sep 2023 18:04:28 +0200 Subject: [PATCH] Fix tilde-expansion for multi-byte unicode chars (#10434) # Description Fixes #10365 Use bytes() instead of chars() to get an actual index that can be used with file.split_at(). utf8 is safe to process bytewise, since an ascii character can never be mistaken for a non-ascii character # User-Facing Changes # Tests + Formatting - [x] Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - [x] `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - [x] `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - [x] `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library # After Submitting --- crates/nu-path/src/tilde.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/nu-path/src/tilde.rs b/crates/nu-path/src/tilde.rs index 48c43a74a..b7df14423 100644 --- a/crates/nu-path/src/tilde.rs +++ b/crates/nu-path/src/tilde.rs @@ -22,9 +22,9 @@ fn expand_tilde_with_home(path: impl AsRef, home: Option) -> Path if !path.starts_with("~") { let string = path.to_string_lossy(); - let mut path_as_string = string.as_ref().chars(); + let mut path_as_string = string.as_ref().bytes(); return match path_as_string.next() { - Some('~') => expand_tilde_with_another_user_home(path), + Some(b'~') => expand_tilde_with_another_user_home(path), _ => path.into(), }; } @@ -121,7 +121,7 @@ fn expand_tilde_with_another_user_home(path: &Path) -> PathBuf { return match path.to_str() { Some(file_path) => { let mut file = file_path.to_string(); - match file_path.chars().position(|c| c == '/' || c == '\\') { + match file_path.find(|c| c == '/' || c == '\\') { None => { file.remove(0); user_home_dir(&file) @@ -185,6 +185,22 @@ mod tests { check_expanded("~//test/"); } + #[test] + fn string_with_tilde_other_user() { + let s = "~someone/test/"; + let expected = format!("{FALLBACK_USER_HOME_BASE_DIR}/someone/test/"); + + assert_eq!(expand_tilde(Path::new(s)), PathBuf::from(expected)); + } + + #[test] + fn string_with_multi_byte_chars() { + let s = "~あ/"; + let expected = format!("{FALLBACK_USER_HOME_BASE_DIR}/あ/"); + + assert_eq!(expand_tilde(Path::new(s)), PathBuf::from(expected)); + } + #[test] fn does_not_expand_tilde_if_tilde_is_not_first_character() { check_not_expanded("1~1");