Auto merge of #58985 - dlrobertson:fix_58980, r=alexreg
Fix segfaults in release build C-variadic fns `va_start` and `va_end` must be called to initialize/cleanup the "spoofed" `VaList` in a Rust defined C-variadic function even if the `VaList` is not used. r? @alexreg Fixes: #58980
This commit is contained in:
commit
b2ea6c86ae
@ -233,8 +233,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
mut bx: Bx,
|
||||
) {
|
||||
if self.fn_ty.c_variadic {
|
||||
if let Some(va_list) = self.va_list_ref {
|
||||
bx.va_end(va_list.llval);
|
||||
match self.va_list_ref {
|
||||
Some(va_list) => {
|
||||
bx.va_end(va_list.llval);
|
||||
}
|
||||
None => {
|
||||
bug!("C-variadic function must have a `va_list_ref`");
|
||||
}
|
||||
}
|
||||
}
|
||||
let llval = match self.fn_ty.ret.mode {
|
||||
|
@ -532,13 +532,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
PassMode::Ignore(IgnoreMode::Zst) => {
|
||||
return local(OperandRef::new_zst(bx.cx(), arg.layout));
|
||||
}
|
||||
PassMode::Ignore(IgnoreMode::CVarArgs) => {
|
||||
let backend_type = bx.cx().immediate_backend_type(arg.layout);
|
||||
return local(OperandRef {
|
||||
val: OperandValue::Immediate(bx.cx().const_undef(backend_type)),
|
||||
layout: arg.layout,
|
||||
});
|
||||
}
|
||||
PassMode::Ignore(IgnoreMode::CVarArgs) => {}
|
||||
PassMode::Direct(_) => {
|
||||
let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
|
||||
bx.set_value_name(llarg, &name);
|
||||
|
19
src/test/codegen/c-variadic-opt.rs
Normal file
19
src/test/codegen/c-variadic-opt.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// compile-flags: -C opt-level=3
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_variadic)]
|
||||
#![no_std]
|
||||
use core::ffi::VaList;
|
||||
|
||||
extern "C" {
|
||||
fn vprintf(fmt: *const i8, ap: VaList) -> i32;
|
||||
}
|
||||
|
||||
// Ensure that `va_start` and `va_end` are properly injected even
|
||||
// when the "spoofed" `VaList` is not used.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn c_variadic_no_use(fmt: *const i8, mut ap: ...) -> i32 {
|
||||
// CHECK: call void @llvm.va_start
|
||||
vprintf(fmt, ap)
|
||||
// CHECK: call void @llvm.va_end
|
||||
}
|
Loading…
Reference in New Issue
Block a user