Skip to content

Commit 640a431

Browse files
authored
Rollup merge of #118464 - wesleywiser:fix_dispose_ordering, r=Nilstrieb
Dispose llvm::TargetMachines prior to llvm::Context being disposed If the TargetMachine is disposed after the Context is disposed, it can lead to use after frees in some cases. I've observed this happening occasionally on code compiled for aarch64-pc-windows-msvc using `-Zstack-protector=strong` but other users have reported AVs from host aarch64-pc-windows-msvc compilers as well. I was not able to extract a self-contained test case yet so there is no accompanying test. Fixes #118462
2 parents 49fadee + 1011078 commit 640a431

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
2525
use std::fs::File;
2626
use std::io;
2727
use std::iter;
28+
use std::mem::ManuallyDrop;
2829
use std::path::Path;
2930
use std::slice;
3031
use std::sync::Arc;
@@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
734735
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
735736
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
736737
let mut module = ModuleCodegen {
737-
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
738+
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
738739
name: thin_module.name().to_string(),
739740
kind: ModuleKind::Regular,
740741
};

compiler/rustc_codegen_llvm/src/lib.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use rustc_span::symbol::Symbol;
5252
use std::any::Any;
5353
use std::ffi::CStr;
5454
use std::io::Write;
55+
use std::mem::ManuallyDrop;
5556

5657
mod back {
5758
pub mod archive;
@@ -407,8 +408,9 @@ pub struct ModuleLlvm {
407408
llcx: &'static mut llvm::Context,
408409
llmod_raw: *const llvm::Module,
409410

410-
// independent from llcx and llmod_raw, resources get disposed by drop impl
411-
tm: OwnedTargetMachine,
411+
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
412+
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
413+
tm: ManuallyDrop<OwnedTargetMachine>,
412414
}
413415

414416
unsafe impl Send for ModuleLlvm {}
@@ -419,15 +421,23 @@ impl ModuleLlvm {
419421
unsafe {
420422
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
421423
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
422-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
424+
ModuleLlvm {
425+
llmod_raw,
426+
llcx,
427+
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
428+
}
423429
}
424430
}
425431

426432
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
427433
unsafe {
428434
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
429435
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
430-
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
436+
ModuleLlvm {
437+
llmod_raw,
438+
llcx,
439+
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
440+
}
431441
}
432442
}
433443

@@ -448,7 +458,7 @@ impl ModuleLlvm {
448458
}
449459
};
450460

451-
Ok(ModuleLlvm { llmod_raw, llcx, tm })
461+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
452462
}
453463
}
454464

@@ -460,6 +470,7 @@ impl ModuleLlvm {
460470
impl Drop for ModuleLlvm {
461471
fn drop(&mut self) {
462472
unsafe {
473+
ManuallyDrop::drop(&mut self.tm);
463474
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
464475
}
465476
}

0 commit comments

Comments
 (0)