fix panic when rustc tries to reduce intermediate filenames length with multi byte chars

The issue cannot be reproduced with the former testcase of creating external crates because
rust refuses to use "external crate 28_找出字符串中第一个匹配项的下标"
because it is not a valid indentifier (starts with number, and contain non ascii chars)

But still using 28_找出字符串中第一个匹配项的下标.rs as a filename is accepted by previous rustc releases
So we consider it valid, and add an integration test for it to catch any regression on other code related to non ascii filenames.
This commit is contained in:
Pierre Tardy
2025-10-23 10:06:59 +02:00
parent 7838ce1a3a
commit c6acffeb78
3 changed files with 37 additions and 5 deletions

View File

@@ -1211,13 +1211,22 @@ fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf {
if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH { if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH {
let filename = path.file_name().unwrap().to_string_lossy(); let filename = path.file_name().unwrap().to_string_lossy();
let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex
let stripped_len = filename.len() - MAX_FILENAME_LENGTH + hash_len; let hyphen_len = 1; // the '-' we insert between hash and suffix
// number of bytes of suffix we can keep so that "hash-<suffix>" fits
let allowed_suffix = MAX_FILENAME_LENGTH.saturating_sub(hash_len + hyphen_len);
// number of bytes to remove from the start
let stripped_bytes = filename.len().saturating_sub(allowed_suffix);
// ensure we don't cut in a middle of a char
let split_at = filename.ceil_char_boundary(stripped_bytes);
let mut hasher = StableHasher::new(); let mut hasher = StableHasher::new();
filename[..stripped_len].hash(&mut hasher); filename[..split_at].hash(&mut hasher);
let hash = hasher.finish::<Hash64>(); let hash = hasher.finish::<Hash64>();
path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..])); path.set_file_name(format!("{:x}-{}", hash, &filename[split_at..]));
} }
path path
} }

View File

@@ -9,8 +9,6 @@
//@ ignore-cross-compile //@ ignore-cross-compile
use std::fs;
use run_make_support::{rfs, rustc}; use run_make_support::{rfs, rustc};
// This test make sure we don't get such following error: // This test make sure we don't get such following error:

View File

@@ -0,0 +1,25 @@
//@ ignore-cross-compile
// gnu ld is confused with intermediate files having multibytes characters in their names:
// = note: ld.exe: cannot find f0d5ff18d6510ebc-???_???_??????????_?_?????_?_???????.d50c2 \
// 4c0c4ea93cc-cgu.0.rcgu.o: Invalid argument
// as this is not something rustc can fix by itself,
// we just skip the test on windows-gnu for now. Hence:
//@ ignore-windows-gnu
use run_make_support::{rfs, rustc};
// This test make sure we don't crash when lto creates output files with long names.
// cn characters can be multi-byte and thus trigger the long filename reduction code more easily.
// we need to make sure that the code is properly generating names at char boundaries.
// as reported in issue #147975
fn main() {
let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"];
for prefix_len in 0..4 {
let prefix: String = std::iter::repeat("_").take(prefix_len).collect();
let main_file = format!("{}ⵅⴻⵎⵎⴻⵎ_ⴷⵉⵎⴰ_ⵖⴻⴼ_ⵢⵉⵙⴻⴽⴽⵉⵍⴻ__ⵡⴰⵟⴰⵙ__ⵢⵉⴱⵢⵜⴻ.rs", prefix);
rfs::write(&main_file, "fn main() {}\n");
for flag in lto_flags {
rustc().input(&main_file).arg(flag).run();
}
}
}