Skip to content

Commit b002407

Browse files
committed
Fix race condition in clang_macro_fallback
1 parent 03d49b6 commit b002407

File tree

7 files changed

+43
-67
lines changed

7 files changed

+43
-67
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen/Cargo.toml

+1
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

+26-24
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use crate::ir::context::BindgenContext;
88
use clang_sys::*;
99
use std::cmp;
10+
use std::path::{Path, PathBuf};
11+
use tempfile::TempDir;
1012

1113
use std::ffi::{CStr, CString};
1214
use std::fmt;
@@ -1822,12 +1824,15 @@ impl TranslationUnit {
18221824
/// Parse a source file into a translation unit.
18231825
pub(crate) fn parse(
18241826
ix: &Index,
1825-
file: &str,
1827+
file: Option<&Path>,
18261828
cmd_args: &[Box<str>],
18271829
unsaved: &[UnsavedFile],
18281830
opts: CXTranslationUnit_Flags,
18291831
) -> Option<TranslationUnit> {
1830-
let fname = CString::new(file).unwrap();
1832+
let fname = match file {
1833+
Some(file) => path_to_cstring(file),
1834+
None => CString::new(vec![]).unwrap(),
1835+
};
18311836
let _c_args: Vec<CString> = cmd_args
18321837
.iter()
18331838
.map(|s| CString::new(s.as_bytes()).unwrap())
@@ -1879,10 +1884,8 @@ impl TranslationUnit {
18791884
}
18801885

18811886
/// 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-
};
1887+
pub(crate) fn save(&mut self, file: &Path) -> Result<(), CXSaveError> {
1888+
let file = path_to_cstring(file);
18861889
let ret = unsafe {
18871890
clang_saveTranslationUnit(
18881891
self.x,
@@ -1913,9 +1916,10 @@ impl Drop for TranslationUnit {
19131916

19141917
/// Translation unit used for macro fallback parsing
19151918
pub(crate) struct FallbackTranslationUnit {
1916-
file_path: String,
1917-
header_path: String,
1918-
pch_path: String,
1919+
temp_dir: TempDir,
1920+
file_path: PathBuf,
1921+
header_path: PathBuf,
1922+
pch_path: PathBuf,
19191923
idx: Box<Index>,
19201924
tu: TranslationUnit,
19211925
}
@@ -1929,9 +1933,10 @@ impl fmt::Debug for FallbackTranslationUnit {
19291933
impl FallbackTranslationUnit {
19301934
/// Create a new fallback translation unit
19311935
pub(crate) fn new(
1932-
file: String,
1933-
header_path: String,
1934-
pch_path: String,
1936+
temp_dir: TempDir,
1937+
file: PathBuf,
1938+
header_path: PathBuf,
1939+
pch_path: PathBuf,
19351940
c_args: &[Box<str>],
19361941
) -> Option<Self> {
19371942
// Create empty file
@@ -1945,12 +1950,13 @@ impl FallbackTranslationUnit {
19451950
let f_index = Box::new(Index::new(true, false));
19461951
let f_translation_unit = TranslationUnit::parse(
19471952
&f_index,
1948-
&file,
1953+
Some(&file),
19491954
c_args,
19501955
&[],
19511956
CXTranslationUnit_None,
19521957
)?;
19531958
Some(FallbackTranslationUnit {
1959+
temp_dir,
19541960
file_path: file,
19551961
header_path,
19561962
pch_path,
@@ -1988,14 +1994,6 @@ impl FallbackTranslationUnit {
19881994
}
19891995
}
19901996

1991-
impl Drop for FallbackTranslationUnit {
1992-
fn drop(&mut self) {
1993-
let _ = std::fs::remove_file(&self.file_path);
1994-
let _ = std::fs::remove_file(&self.header_path);
1995-
let _ = std::fs::remove_file(&self.pch_path);
1996-
}
1997-
}
1998-
19991997
/// A diagnostic message generated while parsing a translation unit.
20001998
pub(crate) struct Diagnostic {
20011999
x: CXDiagnostic,
@@ -2036,9 +2034,9 @@ pub(crate) struct UnsavedFile {
20362034
}
20372035

20382036
impl UnsavedFile {
2039-
/// Construct a new unsaved file with the given `name` and `contents`.
2040-
pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile {
2041-
let name = CString::new(name.as_bytes()).unwrap();
2037+
/// Construct a new unsaved file with the given `path` and `contents`.
2038+
pub(crate) fn new(path: &Path, contents: &str) -> UnsavedFile {
2039+
let name = path_to_cstring(path);
20422040
let contents = CString::new(contents.as_bytes()).unwrap();
20432041
let x = CXUnsavedFile {
20442042
Filename: name.as_ptr(),
@@ -2450,3 +2448,7 @@ impl TargetInfo {
24502448
}
24512449
}
24522450
}
2451+
2452+
fn path_to_cstring(path: &Path) -> CString {
2453+
CString::new(path.to_string_lossy().as_bytes()).unwrap()
2454+
}

bindgen/ir/context.rs

+14-19
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::fs::OpenOptions;
3333
use std::io::Write;
3434
use std::mem;
3535
use std::path::Path;
36+
use tempfile::TempDir;
3637

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

558559
clang::TranslationUnit::parse(
559560
&index,
560-
"",
561+
None,
561562
&options.clang_args,
562563
input_unsaved_files,
563564
parse_options,
@@ -2042,13 +2043,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20422043
&mut self,
20432044
) -> Option<&mut clang::FallbackTranslationUnit> {
20442045
if self.fallback_tu.is_none() {
2045-
let file = format!(
2046-
"{}/.macro_eval.c",
2047-
match self.options().clang_macro_fallback_build_dir {
2048-
Some(ref path) => path.as_os_str().to_str()?,
2049-
None => ".",
2050-
}
2051-
);
2046+
let temp_dir = TempDir::new().unwrap();
2047+
2048+
let file = temp_dir.path().join(".macro_eval.c");
20522049

20532050
let index = clang::Index::new(false, false);
20542051

@@ -2072,15 +2069,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20722069
header_contents +=
20732070
format!("\n#include <{header_name}>").as_str();
20742071
}
2075-
let header_to_precompile = format!(
2076-
"{}/{}",
2077-
match self.options().clang_macro_fallback_build_dir {
2078-
Some(ref path) => path.as_os_str().to_str()?,
2079-
None => ".",
2080-
},
2081-
header_names_to_compile.join("-") + "-precompile.h"
2082-
);
2083-
let pch = header_to_precompile.clone() + ".pch";
2072+
let header_to_precompile = temp_dir
2073+
.path()
2074+
.join(header_names_to_compile.join("-") + "-precompile.h");
2075+
let pch = temp_dir
2076+
.path()
2077+
.join(header_names_to_compile.join("-") + "-precompile.h.pch");
20842078

20852079
let mut header_to_precompile_file = OpenOptions::new()
20862080
.create(true)
@@ -2110,7 +2104,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21102104
);
21112105
let mut tu = clang::TranslationUnit::parse(
21122106
&index,
2113-
&header_to_precompile,
2107+
Some(&header_to_precompile),
21142108
&c_args,
21152109
&[],
21162110
clang_sys::CXTranslationUnit_ForSerialization,
@@ -2119,7 +2113,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21192113

21202114
let mut c_args = vec![
21212115
"-include-pch".to_string().into_boxed_str(),
2122-
pch.clone().into_boxed_str(),
2116+
pch.to_string_lossy().into_owned().into_boxed_str(),
21232117
];
21242118
c_args.extend(
21252119
self.options
@@ -2133,6 +2127,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21332127
.cloned(),
21342128
);
21352129
self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2130+
temp_dir,
21362131
file,
21372132
header_to_precompile,
21382133
pch,

bindgen/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ impl Builder {
359359
std::mem::take(&mut self.options.input_header_contents)
360360
.into_iter()
361361
.map(|(name, contents)| {
362-
clang::UnsavedFile::new(name.as_ref(), contents.as_ref())
362+
clang::UnsavedFile::new((*name).as_ref(), contents.as_ref())
363363
})
364364
.collect::<Vec<_>>();
365365

bindgen/options/cli.rs

-5
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,6 @@ struct BindgenCommand {
459459
/// Enable fallback for clang macro parsing.
460460
#[arg(long)]
461461
clang_macro_fallback: bool,
462-
/// Set path for temporary files generated by fallback for clang macro parsing.
463-
#[arg(long)]
464-
clang_macro_fallback_build_dir: Option<PathBuf>,
465462
/// Use DSTs to represent structures with flexible array members.
466463
#[arg(long)]
467464
flexarray_dst: bool,
@@ -635,7 +632,6 @@ where
635632
override_abi,
636633
wrap_unsafe_ops,
637634
clang_macro_fallback,
638-
clang_macro_fallback_build_dir,
639635
flexarray_dst,
640636
with_derive_custom,
641637
with_derive_custom_struct,
@@ -932,7 +928,6 @@ where
932928
override_abi => |b, (abi, regex)| b.override_abi(abi, regex),
933929
wrap_unsafe_ops,
934930
clang_macro_fallback => |b, _| b.clang_macro_fallback(),
935-
clang_macro_fallback_build_dir,
936931
flexarray_dst,
937932
wrap_static_fns,
938933
wrap_static_fns_path,

bindgen/options/mod.rs

-18
Original file line numberDiff line numberDiff line change
@@ -2148,22 +2148,4 @@ options! {
21482148
},
21492149
as_args: "--clang-macro-fallback",
21502150
}
2151-
/// Path to use for temporary files created by clang macro fallback code like precompiled
2152-
/// headers.
2153-
clang_macro_fallback_build_dir: Option<PathBuf> {
2154-
methods: {
2155-
/// Set a path to a directory to which `.c` and `.h.pch` files should be written for the
2156-
/// purpose of using clang to evaluate macros that can't be easily parsed.
2157-
///
2158-
/// The default location for `.h.pch` files is the directory that the corresponding
2159-
/// `.h` file is located in. The default for the temporary `.c` file used for clang
2160-
/// parsing is the current working directory. Both of these defaults are overridden
2161-
/// by this option.
2162-
pub fn clang_macro_fallback_build_dir<P: AsRef<Path>>(mut self, path: P) -> Self {
2163-
self.options.clang_macro_fallback_build_dir = Some(path.as_ref().to_owned());
2164-
self
2165-
}
2166-
},
2167-
as_args: "--clang-macro-fallback-build-dir",
2168-
}
21692151
}

0 commit comments

Comments
 (0)