fix: read host= from an exe path with non-ASCII characters (#16556)

get_custom_server_from_string located "host=" in s.to_lowercase() and
sliced s with that byte index. Lowercasing can change a character's byte
length ("İ" is 2 bytes, "i̇" is 3), and on Windows the string is the full
exe path, so a profile such as C:\Users\İsmail shifted the slice past the
"h" and host came back empty. The client then fell back to the default
rendezvous server.

"host=" is ASCII, so search s.to_ascii_lowercase(), which keeps byte
offsets.
This commit is contained in:
Leo Camus authored and GitHub committed 2026-10-15 10:30:06 +08:00
1 parent e910029f51
commit e614de83fc
1 file changed
+18 -1
+18 -1
View File
@@ -62,7 +62,7 @@ pub fn get_custom_server_from_string(s: &str) -> ResultType<CustomServer> {
* This allows using a ',' (comma) symbol as a final delimiter.
*/
if s.to_lowercase().contains("host=") {
let stripped = &s[s.to_lowercase().find("host=").unwrap_or(0)..s.len()];
let stripped = &s[s.to_ascii_lowercase().find("host=").unwrap_or(0)..s.len()];
let strs: Vec<&str> = stripped.split(",").collect();
let mut host = String::default();
let mut key = String::default();
@@ -232,4 +232,21 @@ mod test {
get_custom_server_from_string("=0nI900VsFHZVBVdIlncwpHS4V0bOZ0dtVldrpVO4JHdCp0YV5WdzUGZzdnYRVjI6ISeltmIsISMuEjLx4SMiojI0N3boJye.exe")
.unwrap(), lic);
}
#[test]
fn test_filename_license_string_in_non_ascii_path() {
// Windows passes the full exe path, and `İ` grows from 2 to 3 bytes when lowercased.
assert_eq!(
get_custom_server_from_string(
r"C:\Users\İsmail\Downloads\rustdesk-host=server.example.net,key=Zm9vYmFyLiwyCg==.exe"
)
.unwrap(),
CustomServer {
host: "server.example.net".to_owned(),
key: "Zm9vYmFyLiwyCg==".to_owned(),
api: "".to_owned(),
relay: "".to_owned(),
}
);
}
}