authorbors <bors@rust-lang.org> 2025-10-24 18:23:10 UTC
committerbors <bors@rust-lang.org> 2025-10-24 18:23:10 UTC
log2aaa62b89d22b570e560731b03e3d2d6f5c3bbce
treed3e063725ce11b106f3efea2528d2cebe9776013
parentab925646fae038b02bd462cd328ae9eef1639236
parentc6acffeb785e3efa2909f5ec4a4452cb38ddde17

Auto merge of #148018 - tardyp:lto_big_filesize_utf8, r=JonathanBrouwer

fix panic when rustc tries to reduce intermediate filenames len with utf8 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. Fix rust-lang/rust#147975

3 files changed, 37 insertions(+), 5 deletions(-)

compiler/rustc_session/src/config.rs+12-3
......@@ -1211,13 +1211,22 @@ fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf {
12111211 if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH {
12121212 let filename = path.file_name().unwrap().to_string_lossy();
12131213 let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex
1214 let stripped_len = filename.len() - MAX_FILENAME_LENGTH + hash_len;
1214 let hyphen_len = 1; // the '-' we insert between hash and suffix
1215
1216 // number of bytes of suffix we can keep so that "hash-<suffix>" fits
1217 let allowed_suffix = MAX_FILENAME_LENGTH.saturating_sub(hash_len + hyphen_len);
1218
1219 // number of bytes to remove from the start
1220 let stripped_bytes = filename.len().saturating_sub(allowed_suffix);
1221
1222 // ensure we don't cut in a middle of a char
1223 let split_at = filename.ceil_char_boundary(stripped_bytes);
12151224
12161225 let mut hasher = StableHasher::new();
1217 filename[..stripped_len].hash(&mut hasher);
1226 filename[..split_at].hash(&mut hasher);
12181227 let hash = hasher.finish::<Hash64>();
12191228
1220 path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..]));
1229 path.set_file_name(format!("{:x}-{}", hash, &filename[split_at..]));
12211230 }
12221231 path
12231232}
tests/run-make/lto-long-filenames/rmake.rs-2
......@@ -9,8 +9,6 @@
99
1010//@ ignore-cross-compile
1111
12use std::fs;
13
1412use run_make_support::{rfs, rustc};
1513
1614// This test make sure we don't get such following error:
tests/run-make/lto-long-filenames_cn/rmake.rs created+25
......@@ -0,0 +1,25 @@
1//@ ignore-cross-compile
2// gnu ld is confused with intermediate files having multibytes characters in their names:
3// = note: ld.exe: cannot find f0d5ff18d6510ebc-???_???_??????????_?_?????_?_???????.d50c2 \
4// 4c0c4ea93cc-cgu.0.rcgu.o: Invalid argument
5// as this is not something rustc can fix by itself,
6// we just skip the test on windows-gnu for now. Hence:
7//@ ignore-windows-gnu
8
9use run_make_support::{rfs, rustc};
10
11// This test make sure we don't crash when lto creates output files with long names.
12// cn characters can be multi-byte and thus trigger the long filename reduction code more easily.
13// we need to make sure that the code is properly generating names at char boundaries.
14// as reported in issue #147975
15fn main() {
16 let lto_flags = ["-Clto", "-Clto=yes", "-Clto=off", "-Clto=thin", "-Clto=fat"];
17 for prefix_len in 0..4 {
18 let prefix: String = std::iter::repeat("_").take(prefix_len).collect();
19 let main_file = format!("{}ⵅⴻⵎⵎⴻⵎ_ⴷⵉⵎⴰ_ⵖⴻⴼ_ⵢⵉⵙⴻⴽⴽⵉⵍⴻⵏ_ⵏ_ⵡⴰⵟⴰⵙ_ⵏ_ⵢⵉⴱⵢⵜⴻⵏ.rs", prefix);
20 rfs::write(&main_file, "fn main() {}\n");
21 for flag in lto_flags {
22 rustc().input(&main_file).arg(flag).run();
23 }
24 }
25}