Skip to content

Commit d1bc925

Browse files
committed
Fix race condition in clang_macro_fallback
1 parent 937b8d0 commit d1bc925

6 files changed

Lines changed: 37 additions & 46 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ regex = { workspace = true, features = ["std", "unicode-perl"] }
4141
rustc-hash.workspace = true
4242
shlex.workspace = true
4343
syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] }
44+
tempfile.workspace = true
4445

4546
[features]
4647
default = ["logging", "prettyplease", "runtime"]

bindgen/clang.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
use crate::ir::context::BindgenContext;
88
use clang_sys::*;
99
use std::cmp;
10+
use std::os::unix::ffi::OsStrExt;
11+
use std::path::{Path, PathBuf};
12+
use tempfile::TempDir;
1013

1114
use std::ffi::{CStr, CString};
1215
use std::fmt;
@@ -1822,12 +1825,12 @@ impl TranslationUnit {
18221825
/// Parse a source file into a translation unit.
18231826
pub(crate) fn parse(
18241827
ix: &Index,
1825-
file: &str,
1828+
file: &Path,
18261829
cmd_args: &[Box<str>],
18271830
unsaved: &[UnsavedFile],
18281831
opts: CXTranslationUnit_Flags,
18291832
) -> Option<TranslationUnit> {
1830-
let fname = CString::new(file).unwrap();
1833+
let fname = path_to_cstring(file);
18311834
let _c_args: Vec<CString> = cmd_args
18321835
.iter()
18331836
.map(|s| CString::new(s.as_bytes()).unwrap())
@@ -1879,10 +1882,8 @@ impl TranslationUnit {
18791882
}
18801883

18811884
/// Save a translation unit to the given file.
1882-
pub(crate) fn save(&mut self, file: &str) -> Result<(), CXSaveError> {
1883-
let Ok(file) = CString::new(file) else {
1884-
return Err(CXSaveError_Unknown);
1885-
};
1885+
pub(crate) fn save(&mut self, file: &Path) -> Result<(), CXSaveError> {
1886+
let file = path_to_cstring(file);
18861887
let ret = unsafe {
18871888
clang_saveTranslationUnit(
18881889
self.x,
@@ -1913,8 +1914,9 @@ impl Drop for TranslationUnit {
19131914

19141915
/// Translation unit used for macro fallback parsing
19151916
pub(crate) struct FallbackTranslationUnit {
1916-
file_path: String,
1917-
pch_path: String,
1917+
temp_dir: TempDir,
1918+
file_path: PathBuf,
1919+
pch_path: PathBuf,
19181920
idx: Box<Index>,
19191921
tu: TranslationUnit,
19201922
}
@@ -1928,8 +1930,9 @@ impl fmt::Debug for FallbackTranslationUnit {
19281930
impl FallbackTranslationUnit {
19291931
/// Create a new fallback translation unit
19301932
pub(crate) fn new(
1931-
file: String,
1932-
pch_path: String,
1933+
temp_dir: TempDir,
1934+
file: PathBuf,
1935+
pch_path: PathBuf,
19331936
c_args: &[Box<str>],
19341937
) -> Option<Self> {
19351938
// Create empty file
@@ -1949,6 +1952,7 @@ impl FallbackTranslationUnit {
19491952
CXTranslationUnit_None,
19501953
)?;
19511954
Some(FallbackTranslationUnit {
1955+
temp_dir,
19521956
file_path: file,
19531957
pch_path,
19541958
tu: f_translation_unit,
@@ -1985,13 +1989,6 @@ impl FallbackTranslationUnit {
19851989
}
19861990
}
19871991

1988-
impl Drop for FallbackTranslationUnit {
1989-
fn drop(&mut self) {
1990-
let _ = std::fs::remove_file(&self.file_path);
1991-
let _ = std::fs::remove_file(&self.pch_path);
1992-
}
1993-
}
1994-
19951992
/// A diagnostic message generated while parsing a translation unit.
19961993
pub(crate) struct Diagnostic {
19971994
x: CXDiagnostic,
@@ -2032,9 +2029,9 @@ pub(crate) struct UnsavedFile {
20322029
}
20332030

20342031
impl UnsavedFile {
2035-
/// Construct a new unsaved file with the given `name` and `contents`.
2036-
pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile {
2037-
let name = CString::new(name.as_bytes()).unwrap();
2032+
/// Construct a new unsaved file with the given `path` and `contents`.
2033+
pub(crate) fn new(path: &Path, contents: &str) -> UnsavedFile {
2034+
let name = path_to_cstring(path);
20382035
let contents = CString::new(contents.as_bytes()).unwrap();
20392036
let x = CXUnsavedFile {
20402037
Filename: name.as_ptr(),
@@ -2447,3 +2444,7 @@ impl TargetInfo {
24472444
}
24482445
}
24492446
}
2447+
2448+
fn path_to_cstring(path: &Path) -> CString {
2449+
CString::new(path.as_os_str().as_bytes()).unwrap()
2450+
}

bindgen/ir/context.rs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use std::cell::{Cell, RefCell};
3232
use std::collections::{BTreeSet, HashMap as StdHashMap};
3333
use std::mem;
3434
use std::path::Path;
35+
use tempfile::TempDir;
3536

3637
/// An identifier for some kind of IR item.
3738
#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
@@ -556,7 +557,7 @@ impl BindgenContext {
556557

557558
clang::TranslationUnit::parse(
558559
&index,
559-
"",
560+
"".as_ref(),
560561
&options.clang_args,
561562
input_unsaved_files,
562563
parse_options,
@@ -2045,13 +2046,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20452046
&mut self,
20462047
) -> Option<&mut clang::FallbackTranslationUnit> {
20472048
if self.fallback_tu.is_none() {
2048-
let file = format!(
2049-
"{}/.macro_eval.c",
2050-
match self.options().clang_macro_fallback_build_dir {
2051-
Some(ref path) => path.as_os_str().to_str()?,
2052-
None => ".",
2053-
}
2054-
);
2049+
let temp_dir = TempDir::new().unwrap();
2050+
2051+
let file = temp_dir.path().join(".macro_eval.c");
20552052

20562053
let index = clang::Index::new(false, false);
20572054

@@ -2079,14 +2076,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20792076
header_names_to_compile
20802077
.push(header_name.split(".h").next()?.to_string());
20812078
}
2082-
let pch = format!(
2083-
"{}/{}",
2084-
match self.options().clang_macro_fallback_build_dir {
2085-
Some(ref path) => path.as_os_str().to_str()?,
2086-
None => ".",
2087-
},
2088-
header_names_to_compile.join("-") + "-precompile.h.pch"
2089-
);
2079+
let pch = temp_dir
2080+
.path()
2081+
.join(header_names_to_compile.join("-") + "-precompile.h.pch");
20902082

20912083
let mut c_args = self.options.fallback_clang_args.clone();
20922084
c_args.push("-x".to_string().into_boxed_str());
@@ -2100,7 +2092,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21002092
}
21012093
let mut tu = clang::TranslationUnit::parse(
21022094
&index,
2103-
single_header,
2095+
(&**single_header).as_ref(),
21042096
&c_args,
21052097
&[],
21062098
clang_sys::CXTranslationUnit_ForSerialization,
@@ -2109,7 +2101,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21092101

21102102
let mut c_args = vec![
21112103
"-include-pch".to_string().into_boxed_str(),
2112-
pch.clone().into_boxed_str(),
2104+
pch.to_string_lossy().into_owned().into_boxed_str(),
21132105
];
21142106
let mut skip_next = false;
21152107
for arg in &self.options.fallback_clang_args {
@@ -2121,8 +2113,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21212113
c_args.push(arg.clone());
21222114
}
21232115
}
2124-
self.fallback_tu =
2125-
Some(clang::FallbackTranslationUnit::new(file, pch, &c_args)?);
2116+
self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2117+
temp_dir, file, pch, &c_args,
2118+
)?);
21262119
}
21272120

21282121
self.fallback_tu.as_mut()

bindgen/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ impl Builder {
365365
std::mem::take(&mut self.options.input_header_contents)
366366
.into_iter()
367367
.map(|(name, contents)| {
368-
clang::UnsavedFile::new(name.as_ref(), contents.as_ref())
368+
clang::UnsavedFile::new((*name).as_ref(), contents.as_ref())
369369
})
370370
.collect::<Vec<_>>();
371371

bindgen/options/cli.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,6 @@ struct BindgenCommand {
499499
/// Enable fallback for clang macro parsing.
500500
#[arg(long)]
501501
clang_macro_fallback: bool,
502-
/// Set path for temporary files generated by fallback for clang macro parsing.
503-
#[arg(long)]
504-
clang_macro_fallback_build_dir: Option<PathBuf>,
505502
/// Use DSTs to represent structures with flexible array members.
506503
#[arg(long)]
507504
flexarray_dst: bool,
@@ -695,7 +692,6 @@ where
695692
override_abi,
696693
wrap_unsafe_ops,
697694
clang_macro_fallback,
698-
clang_macro_fallback_build_dir,
699695
flexarray_dst,
700696
with_derive_custom,
701697
with_derive_custom_struct,
@@ -1001,7 +997,6 @@ where
1001997
override_abi => |b, (abi, regex)| b.override_abi(abi, regex),
1002998
wrap_unsafe_ops,
1003999
clang_macro_fallback => |b, _| b.clang_macro_fallback(),
1004-
clang_macro_fallback_build_dir,
10051000
flexarray_dst,
10061001
wrap_static_fns,
10071002
wrap_static_fns_path,

0 commit comments

Comments
 (0)