Skip to content

Commit 6b9767d

Browse files
committed
Fix ICE when there is a non-Unicode entry in the incremental crate directory
1 parent 5260893 commit 6b9767d

File tree

6 files changed

+47
-17
lines changed

6 files changed

+47
-17
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3341,6 +3341,7 @@ dependencies = [
33413341
name = "run_make_support"
33423342
version = "0.0.0"
33433343
dependencies = [
3344+
"libc",
33443345
"object 0.34.0",
33453346
"regex",
33463347
"wasmparser",

compiler/rustc_incremental/src/persist/fs.rs

+19-17
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,11 @@ pub fn query_cache_path(sess: &Session) -> PathBuf {
162162
fn lock_file_path(session_dir: &Path) -> PathBuf {
163163
let crate_dir = session_dir.parent().unwrap();
164164

165-
let directory_name = session_dir.file_name().unwrap().to_string_lossy();
166-
assert_no_characters_lost(&directory_name);
165+
let directory_name = session_dir
166+
.file_name()
167+
.unwrap()
168+
.to_str()
169+
.expect("malformed session dir name: contains non-Unicode characters");
167170

168171
let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect();
169172
if dash_indices.len() != 3 {
@@ -329,8 +332,11 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) {
329332

330333
debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display());
331334

332-
let old_sub_dir_name = incr_comp_session_dir.file_name().unwrap().to_string_lossy();
333-
assert_no_characters_lost(&old_sub_dir_name);
335+
let old_sub_dir_name = incr_comp_session_dir
336+
.file_name()
337+
.unwrap()
338+
.to_str()
339+
.expect("malformed session dir name: contains non-Unicode characters");
334340

335341
// Keep the 's-{timestamp}-{random-number}' prefix, but replace the
336342
// '-working' part with the SVH of the crate
@@ -527,8 +533,10 @@ where
527533
for session_dir in iter {
528534
debug!("find_source_directory_in_iter - inspecting `{}`", session_dir.display());
529535

530-
let directory_name = session_dir.file_name().unwrap().to_string_lossy();
531-
assert_no_characters_lost(&directory_name);
536+
let Some(directory_name) = session_dir.file_name().unwrap().to_str() else {
537+
debug!("find_source_directory_in_iter - ignoring");
538+
continue;
539+
};
532540

533541
if source_directories_already_tried.contains(&session_dir)
534542
|| !is_session_directory(&directory_name)
@@ -619,12 +627,6 @@ fn crate_path(sess: &Session) -> PathBuf {
619627
incr_dir.join(crate_name)
620628
}
621629

622-
fn assert_no_characters_lost(s: &str) {
623-
if s.contains('\u{FFFD}') {
624-
bug!("Could not losslessly convert '{}'.", s)
625-
}
626-
}
627-
628630
fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool {
629631
timestamp < SystemTime::now() - Duration::from_secs(10)
630632
}
@@ -657,14 +659,14 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<
657659
};
658660

659661
let entry_name = dir_entry.file_name();
660-
let entry_name = entry_name.to_string_lossy();
662+
let Some(entry_name) = entry_name.to_str() else {
663+
continue;
664+
};
661665

662666
if is_session_directory_lock_file(&entry_name) {
663-
assert_no_characters_lost(&entry_name);
664-
lock_files.insert(entry_name.into_owned());
667+
lock_files.insert(entry_name.to_string());
665668
} else if is_session_directory(&entry_name) {
666-
assert_no_characters_lost(&entry_name);
667-
session_directories.insert(entry_name.into_owned());
669+
session_directories.insert(entry_name.to_string());
668670
} else {
669671
// This is something we don't know, leave it alone
670672
}

src/tools/run-make-support/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ edition = "2021"
77
object = "0.34.0"
88
wasmparser = "0.118.2"
99
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
10+
libc = "0.2.153"

src/tools/run-make-support/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::env;
1212
use std::path::{Path, PathBuf};
1313
use std::process::{Command, Output};
1414

15+
pub use libc;
1516
pub use object;
1617
pub use regex;
1718
pub use wasmparser;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
extern crate run_make_support;
2+
3+
use run_make_support::{libc, rustc, tmp_dir};
4+
5+
fn main() {
6+
#[cfg(unix)]
7+
let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]);
8+
#[cfg(windows)]
9+
let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
10+
match std::fs::create_dir(tmp_dir().join(&non_unicode)) {
11+
Err(e) if e.raw_os_error() == Some(libc::EILSEQ) => {
12+
// Filesystem doesn't support non-Unicode paths.
13+
return;
14+
}
15+
Err(e) => panic!("error creating non-Unicode directory: {e}"),
16+
_ => {}
17+
}
18+
let incr_dir = tmp_dir().join("incr-dir");
19+
rustc().input("foo.rs").incremental(&incr_dir).run();
20+
for crate_dir in std::fs::read_dir(&incr_dir).unwrap() {
21+
std::fs::create_dir(crate_dir.unwrap().path().join(&non_unicode)).unwrap();
22+
}
23+
rustc().input("foo.rs").incremental(&incr_dir).run();
24+
}

0 commit comments

Comments
 (0)