Skip to content

Commit 24a0f20

Browse files
committed
Fix race condition in clang_macro_fallback
1 parent 76920aa commit 24a0f20

File tree

7 files changed

+146
-170
lines changed

7 files changed

+146
-170
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

+61-59
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;
@@ -246,11 +248,10 @@ impl Cursor {
246248
pub(crate) fn is_toplevel(&self) -> bool {
247249
let mut semantic_parent = self.fallible_semantic_parent();
248250

249-
while semantic_parent.is_some() &&
250-
(semantic_parent.unwrap().kind() == CXCursor_Namespace ||
251-
semantic_parent.unwrap().kind() ==
252-
CXCursor_NamespaceAlias ||
253-
semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
251+
while semantic_parent.is_some()
252+
&& (semantic_parent.unwrap().kind() == CXCursor_Namespace
253+
|| semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias
254+
|| semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
254255
{
255256
semantic_parent =
256257
semantic_parent.unwrap().fallible_semantic_parent();
@@ -267,9 +268,9 @@ impl Cursor {
267268
pub(crate) fn is_template_like(&self) -> bool {
268269
matches!(
269270
self.kind(),
270-
CXCursor_ClassTemplate |
271-
CXCursor_ClassTemplatePartialSpecialization |
272-
CXCursor_TypeAliasTemplateDecl
271+
CXCursor_ClassTemplate
272+
| CXCursor_ClassTemplatePartialSpecialization
273+
| CXCursor_TypeAliasTemplateDecl
273274
)
274275
}
275276

@@ -296,9 +297,9 @@ impl Cursor {
296297
/// Is the referent a fully specialized template specialization without any
297298
/// remaining free template arguments?
298299
pub(crate) fn is_fully_specialized_template(&self) -> bool {
299-
self.is_template_specialization() &&
300-
self.kind() != CXCursor_ClassTemplatePartialSpecialization &&
301-
self.num_template_args().unwrap_or(0) > 0
300+
self.is_template_specialization()
301+
&& self.kind() != CXCursor_ClassTemplatePartialSpecialization
302+
&& self.num_template_args().unwrap_or(0) > 0
302303
}
303304

304305
/// Is the referent a template specialization that still has remaining free
@@ -324,9 +325,9 @@ impl Cursor {
324325
pub(crate) fn is_template_parameter(&self) -> bool {
325326
matches!(
326327
self.kind(),
327-
CXCursor_TemplateTemplateParameter |
328-
CXCursor_TemplateTypeParameter |
329-
CXCursor_NonTypeTemplateParameter
328+
CXCursor_TemplateTemplateParameter
329+
| CXCursor_TemplateTypeParameter
330+
| CXCursor_NonTypeTemplateParameter
330331
)
331332
}
332333

@@ -664,9 +665,9 @@ impl Cursor {
664665
// inline function without a definition, and it's not a defaulted
665666
// function, we can reasonably safely conclude that it's a deleted
666667
// function.
667-
self.is_inlined_function() &&
668-
self.definition().is_none() &&
669-
!self.is_defaulted_function()
668+
self.is_inlined_function()
669+
&& self.definition().is_none()
670+
&& !self.is_defaulted_function()
670671
}
671672

672673
/// Is the referent a bit field declaration?
@@ -788,11 +789,11 @@ impl Cursor {
788789
let found_attr = &mut found_attrs[idx];
789790
if !*found_attr {
790791
// `attr.name` and` attr.token_kind` are checked against unexposed attributes only.
791-
if attr.kind == Some(kind) ||
792-
(kind == CXCursor_UnexposedAttr &&
793-
cur.tokens().iter().any(|t| {
794-
t.kind == attr.token_kind &&
795-
t.spelling() == attr.name
792+
if attr.kind == Some(kind)
793+
|| (kind == CXCursor_UnexposedAttr
794+
&& cur.tokens().iter().any(|t| {
795+
t.kind == attr.token_kind
796+
&& t.spelling() == attr.name
796797
}))
797798
{
798799
*found_attr = true;
@@ -1408,12 +1409,12 @@ impl Type {
14081409
/// to.
14091410
pub(crate) fn pointee_type(&self) -> Option<Type> {
14101411
match self.kind() {
1411-
CXType_Pointer |
1412-
CXType_RValueReference |
1413-
CXType_LValueReference |
1414-
CXType_MemberPointer |
1415-
CXType_BlockPointer |
1416-
CXType_ObjCObjectPointer => {
1412+
CXType_Pointer
1413+
| CXType_RValueReference
1414+
| CXType_LValueReference
1415+
| CXType_MemberPointer
1416+
| CXType_BlockPointer
1417+
| CXType_ObjCObjectPointer => {
14171418
let ret = Type {
14181419
x: unsafe { clang_getPointeeType(self.x) },
14191420
};
@@ -1516,12 +1517,12 @@ impl Type {
15161517
// Yep, the spelling of this containing type-parameter is extremely
15171518
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
15181519
// reduce it enough :(
1519-
self.template_args().is_some_and(|args| args.len() > 0) &&
1520-
!matches!(
1520+
self.template_args().is_some_and(|args| args.len() > 0)
1521+
&& !matches!(
15211522
self.declaration().kind(),
1522-
CXCursor_ClassTemplatePartialSpecialization |
1523-
CXCursor_TypeAliasTemplateDecl |
1524-
CXCursor_TemplateTemplateParameter
1523+
CXCursor_ClassTemplatePartialSpecialization
1524+
| CXCursor_TypeAliasTemplateDecl
1525+
| CXCursor_TemplateTemplateParameter
15251526
)
15261527
}
15271528

@@ -1546,9 +1547,9 @@ impl Type {
15461547
.is_match(spelling.as_ref())
15471548
}
15481549

1549-
self.kind() == CXType_Unexposed &&
1550-
(hacky_parse_associated_type(self.spelling()) ||
1551-
hacky_parse_associated_type(
1550+
self.kind() == CXType_Unexposed
1551+
&& (hacky_parse_associated_type(self.spelling())
1552+
|| hacky_parse_associated_type(
15521553
self.canonical_type().spelling(),
15531554
))
15541555
}
@@ -1822,12 +1823,15 @@ impl TranslationUnit {
18221823
/// Parse a source file into a translation unit.
18231824
pub(crate) fn parse(
18241825
ix: &Index,
1825-
file: &str,
1826+
file: Option<&Path>,
18261827
cmd_args: &[Box<str>],
18271828
unsaved: &[UnsavedFile],
18281829
opts: CXTranslationUnit_Flags,
18291830
) -> Option<TranslationUnit> {
1830-
let fname = CString::new(file).unwrap();
1831+
let fname = match file {
1832+
Some(file) => path_to_cstring(file),
1833+
None => CString::new(vec![]).unwrap(),
1834+
};
18311835
let _c_args: Vec<CString> = cmd_args
18321836
.iter()
18331837
.map(|s| CString::new(s.as_bytes()).unwrap())
@@ -1879,10 +1883,8 @@ impl TranslationUnit {
18791883
}
18801884

18811885
/// 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-
};
1886+
pub(crate) fn save(&mut self, file: &Path) -> Result<(), CXSaveError> {
1887+
let file = path_to_cstring(file);
18861888
let ret = unsafe {
18871889
clang_saveTranslationUnit(
18881890
self.x,
@@ -1913,8 +1915,9 @@ impl Drop for TranslationUnit {
19131915

19141916
/// Translation unit used for macro fallback parsing
19151917
pub(crate) struct FallbackTranslationUnit {
1916-
file_path: String,
1917-
pch_path: String,
1918+
temp_dir: TempDir,
1919+
file_path: PathBuf,
1920+
pch_path: PathBuf,
19181921
idx: Box<Index>,
19191922
tu: TranslationUnit,
19201923
}
@@ -1928,8 +1931,9 @@ impl fmt::Debug for FallbackTranslationUnit {
19281931
impl FallbackTranslationUnit {
19291932
/// Create a new fallback translation unit
19301933
pub(crate) fn new(
1931-
file: String,
1932-
pch_path: String,
1934+
temp_dir: TempDir,
1935+
file: PathBuf,
1936+
pch_path: PathBuf,
19331937
c_args: &[Box<str>],
19341938
) -> Option<Self> {
19351939
// Create empty file
@@ -1943,12 +1947,13 @@ impl FallbackTranslationUnit {
19431947
let f_index = Box::new(Index::new(true, false));
19441948
let f_translation_unit = TranslationUnit::parse(
19451949
&f_index,
1946-
&file,
1950+
Some(&file),
19471951
c_args,
19481952
&[],
19491953
CXTranslationUnit_None,
19501954
)?;
19511955
Some(FallbackTranslationUnit {
1956+
temp_dir,
19521957
file_path: file,
19531958
pch_path,
19541959
tu: f_translation_unit,
@@ -1985,13 +1990,6 @@ impl FallbackTranslationUnit {
19851990
}
19861991
}
19871992

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-
19951993
/// A diagnostic message generated while parsing a translation unit.
19961994
pub(crate) struct Diagnostic {
19971995
x: CXDiagnostic,
@@ -2032,9 +2030,9 @@ pub(crate) struct UnsavedFile {
20322030
}
20332031

20342032
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();
2033+
/// Construct a new unsaved file with the given `path` and `contents`.
2034+
pub(crate) fn new(path: &Path, contents: &str) -> UnsavedFile {
2035+
let name = path_to_cstring(path);
20382036
let contents = CString::new(contents.as_bytes()).unwrap();
20392037
let x = CXUnsavedFile {
20402038
Filename: name.as_ptr(),
@@ -2309,8 +2307,8 @@ impl EvalResult {
23092307
{
23102308
let mut found_cant_eval = false;
23112309
cursor.visit(|c| {
2312-
if c.kind() == CXCursor_TypeRef &&
2313-
c.cur_type().canonical_type().kind() == CXType_Unexposed
2310+
if c.kind() == CXCursor_TypeRef
2311+
&& c.cur_type().canonical_type().kind() == CXType_Unexposed
23142312
{
23152313
found_cant_eval = true;
23162314
return CXChildVisit_Break;
@@ -2446,3 +2444,7 @@ impl TargetInfo {
24462444
}
24472445
}
24482446
}
2447+
2448+
fn path_to_cstring(path: &Path) -> CString {
2449+
CString::new(path.to_string_lossy().as_bytes()).unwrap()
2450+
}

0 commit comments

Comments
 (0)