Skip to content

Commit

Permalink
Fix race condition in clang_macro_fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
HKalbasi committed Feb 10, 2025
1 parent 76920aa commit 24a0f20
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 170 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bindgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ regex = { workspace = true, features = ["std", "unicode-perl"] }
rustc-hash.workspace = true
shlex.workspace = true
syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] }
tempfile.workspace = true

[features]
default = ["logging", "prettyplease", "runtime"]
Expand Down
120 changes: 61 additions & 59 deletions bindgen/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use crate::ir::context::BindgenContext;
use clang_sys::*;
use std::cmp;
use std::path::{Path, PathBuf};
use tempfile::TempDir;

use std::ffi::{CStr, CString};
use std::fmt;
Expand Down Expand Up @@ -246,11 +248,10 @@ impl Cursor {
pub(crate) fn is_toplevel(&self) -> bool {
let mut semantic_parent = self.fallible_semantic_parent();

while semantic_parent.is_some() &&
(semantic_parent.unwrap().kind() == CXCursor_Namespace ||
semantic_parent.unwrap().kind() ==
CXCursor_NamespaceAlias ||
semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
while semantic_parent.is_some()
&& (semantic_parent.unwrap().kind() == CXCursor_Namespace
|| semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias
|| semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
{
semantic_parent =
semantic_parent.unwrap().fallible_semantic_parent();
Expand All @@ -267,9 +268,9 @@ impl Cursor {
pub(crate) fn is_template_like(&self) -> bool {
matches!(
self.kind(),
CXCursor_ClassTemplate |
CXCursor_ClassTemplatePartialSpecialization |
CXCursor_TypeAliasTemplateDecl
CXCursor_ClassTemplate
| CXCursor_ClassTemplatePartialSpecialization
| CXCursor_TypeAliasTemplateDecl
)
}

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

/// Is the referent a template specialization that still has remaining free
Expand All @@ -324,9 +325,9 @@ impl Cursor {
pub(crate) fn is_template_parameter(&self) -> bool {
matches!(
self.kind(),
CXCursor_TemplateTemplateParameter |
CXCursor_TemplateTypeParameter |
CXCursor_NonTypeTemplateParameter
CXCursor_TemplateTemplateParameter
| CXCursor_TemplateTypeParameter
| CXCursor_NonTypeTemplateParameter
)
}

Expand Down Expand Up @@ -664,9 +665,9 @@ impl Cursor {
// inline function without a definition, and it's not a defaulted
// function, we can reasonably safely conclude that it's a deleted
// function.
self.is_inlined_function() &&
self.definition().is_none() &&
!self.is_defaulted_function()
self.is_inlined_function()
&& self.definition().is_none()
&& !self.is_defaulted_function()
}

/// Is the referent a bit field declaration?
Expand Down Expand Up @@ -788,11 +789,11 @@ impl Cursor {
let found_attr = &mut found_attrs[idx];
if !*found_attr {
// `attr.name` and` attr.token_kind` are checked against unexposed attributes only.
if attr.kind == Some(kind) ||
(kind == CXCursor_UnexposedAttr &&
cur.tokens().iter().any(|t| {
t.kind == attr.token_kind &&
t.spelling() == attr.name
if attr.kind == Some(kind)
|| (kind == CXCursor_UnexposedAttr
&& cur.tokens().iter().any(|t| {
t.kind == attr.token_kind
&& t.spelling() == attr.name
}))
{
*found_attr = true;
Expand Down Expand Up @@ -1408,12 +1409,12 @@ impl Type {
/// to.
pub(crate) fn pointee_type(&self) -> Option<Type> {
match self.kind() {
CXType_Pointer |
CXType_RValueReference |
CXType_LValueReference |
CXType_MemberPointer |
CXType_BlockPointer |
CXType_ObjCObjectPointer => {
CXType_Pointer
| CXType_RValueReference
| CXType_LValueReference
| CXType_MemberPointer
| CXType_BlockPointer
| CXType_ObjCObjectPointer => {
let ret = Type {
x: unsafe { clang_getPointeeType(self.x) },
};
Expand Down Expand Up @@ -1516,12 +1517,12 @@ impl Type {
// Yep, the spelling of this containing type-parameter is extremely
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
// reduce it enough :(
self.template_args().is_some_and(|args| args.len() > 0) &&
!matches!(
self.template_args().is_some_and(|args| args.len() > 0)
&& !matches!(
self.declaration().kind(),
CXCursor_ClassTemplatePartialSpecialization |
CXCursor_TypeAliasTemplateDecl |
CXCursor_TemplateTemplateParameter
CXCursor_ClassTemplatePartialSpecialization
| CXCursor_TypeAliasTemplateDecl
| CXCursor_TemplateTemplateParameter
)
}

Expand All @@ -1546,9 +1547,9 @@ impl Type {
.is_match(spelling.as_ref())
}

self.kind() == CXType_Unexposed &&
(hacky_parse_associated_type(self.spelling()) ||
hacky_parse_associated_type(
self.kind() == CXType_Unexposed
&& (hacky_parse_associated_type(self.spelling())
|| hacky_parse_associated_type(
self.canonical_type().spelling(),
))
}
Expand Down Expand Up @@ -1822,12 +1823,15 @@ impl TranslationUnit {
/// Parse a source file into a translation unit.
pub(crate) fn parse(
ix: &Index,
file: &str,
file: Option<&Path>,
cmd_args: &[Box<str>],
unsaved: &[UnsavedFile],
opts: CXTranslationUnit_Flags,
) -> Option<TranslationUnit> {
let fname = CString::new(file).unwrap();
let fname = match file {
Some(file) => path_to_cstring(file),
None => CString::new(vec![]).unwrap(),
};
let _c_args: Vec<CString> = cmd_args
.iter()
.map(|s| CString::new(s.as_bytes()).unwrap())
Expand Down Expand Up @@ -1879,10 +1883,8 @@ impl TranslationUnit {
}

/// Save a translation unit to the given file.
pub(crate) fn save(&mut self, file: &str) -> Result<(), CXSaveError> {
let Ok(file) = CString::new(file) else {
return Err(CXSaveError_Unknown);
};
pub(crate) fn save(&mut self, file: &Path) -> Result<(), CXSaveError> {
let file = path_to_cstring(file);
let ret = unsafe {
clang_saveTranslationUnit(
self.x,
Expand Down Expand Up @@ -1913,8 +1915,9 @@ impl Drop for TranslationUnit {

/// Translation unit used for macro fallback parsing
pub(crate) struct FallbackTranslationUnit {
file_path: String,
pch_path: String,
temp_dir: TempDir,
file_path: PathBuf,
pch_path: PathBuf,
idx: Box<Index>,
tu: TranslationUnit,
}
Expand All @@ -1928,8 +1931,9 @@ impl fmt::Debug for FallbackTranslationUnit {
impl FallbackTranslationUnit {
/// Create a new fallback translation unit
pub(crate) fn new(
file: String,
pch_path: String,
temp_dir: TempDir,
file: PathBuf,
pch_path: PathBuf,
c_args: &[Box<str>],
) -> Option<Self> {
// Create empty file
Expand All @@ -1943,12 +1947,13 @@ impl FallbackTranslationUnit {
let f_index = Box::new(Index::new(true, false));
let f_translation_unit = TranslationUnit::parse(
&f_index,
&file,
Some(&file),
c_args,
&[],
CXTranslationUnit_None,
)?;
Some(FallbackTranslationUnit {
temp_dir,
file_path: file,
pch_path,
tu: f_translation_unit,
Expand Down Expand Up @@ -1985,13 +1990,6 @@ impl FallbackTranslationUnit {
}
}

impl Drop for FallbackTranslationUnit {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.file_path);
let _ = std::fs::remove_file(&self.pch_path);
}
}

/// A diagnostic message generated while parsing a translation unit.
pub(crate) struct Diagnostic {
x: CXDiagnostic,
Expand Down Expand Up @@ -2032,9 +2030,9 @@ pub(crate) struct UnsavedFile {
}

impl UnsavedFile {
/// Construct a new unsaved file with the given `name` and `contents`.
pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile {
let name = CString::new(name.as_bytes()).unwrap();
/// Construct a new unsaved file with the given `path` and `contents`.
pub(crate) fn new(path: &Path, contents: &str) -> UnsavedFile {
let name = path_to_cstring(path);
let contents = CString::new(contents.as_bytes()).unwrap();
let x = CXUnsavedFile {
Filename: name.as_ptr(),
Expand Down Expand Up @@ -2309,8 +2307,8 @@ impl EvalResult {
{
let mut found_cant_eval = false;
cursor.visit(|c| {
if c.kind() == CXCursor_TypeRef &&
c.cur_type().canonical_type().kind() == CXType_Unexposed
if c.kind() == CXCursor_TypeRef
&& c.cur_type().canonical_type().kind() == CXType_Unexposed
{
found_cant_eval = true;
return CXChildVisit_Break;
Expand Down Expand Up @@ -2446,3 +2444,7 @@ impl TargetInfo {
}
}
}

fn path_to_cstring(path: &Path) -> CString {
CString::new(path.to_string_lossy().as_bytes()).unwrap()
}
Loading

0 comments on commit 24a0f20

Please sign in to comment.