Fix UB in LLVM FFI when passing zero or >1 bundle
Rust passes a *const &OperandBundleDef to these APIs, usually from a Vec<&OperandBundleDef> or so. Previously we were dereferencing that pointer and passing it to the ArrayRef constructor with some length (N). This meant that if the length was 0, we were dereferencing a pointer to nowhere, and if the length was >1 then loading the *second* element somewhere in LLVM would've been reading past the end. Since Rust can't hold OperandBundleDef by-value we're forced to indirect through a vector that copies out the OperandBundleDefs from the by-reference list on the Rust side in order to match the LLVM expected API.
This commit is contained in:
parent
a8a88fe524
commit
bf3deccdad
1 changed files with 29 additions and 6 deletions
|
@ -1524,13 +1524,21 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
|
||||||
|
|
||||||
extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||||
LLVMValueRef *Args, unsigned NumArgs,
|
LLVMValueRef *Args, unsigned NumArgs,
|
||||||
OperandBundleDef **OpBundles,
|
OperandBundleDef **OpBundlesIndirect,
|
||||||
unsigned NumOpBundles) {
|
unsigned NumOpBundles) {
|
||||||
Value *Callee = unwrap(Fn);
|
Value *Callee = unwrap(Fn);
|
||||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||||
|
|
||||||
|
// FIXME: Is there a way around this?
|
||||||
|
SmallVector<OperandBundleDef> OpBundles;
|
||||||
|
OpBundles.reserve(NumOpBundles);
|
||||||
|
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||||
|
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return wrap(unwrap(B)->CreateCall(
|
return wrap(unwrap(B)->CreateCall(
|
||||||
FTy, Callee, ArrayRef<Value*>(unwrap(Args), NumArgs),
|
FTy, Callee, ArrayRef<Value*>(unwrap(Args), NumArgs),
|
||||||
ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles)));
|
ArrayRef<OperandBundleDef>(OpBundles)));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
|
extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
|
||||||
|
@ -1570,13 +1578,21 @@ extern "C" LLVMValueRef
|
||||||
LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||||
LLVMValueRef *Args, unsigned NumArgs,
|
LLVMValueRef *Args, unsigned NumArgs,
|
||||||
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
|
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
|
||||||
OperandBundleDef **OpBundles, unsigned NumOpBundles,
|
OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
|
||||||
const char *Name) {
|
const char *Name) {
|
||||||
Value *Callee = unwrap(Fn);
|
Value *Callee = unwrap(Fn);
|
||||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||||
|
|
||||||
|
// FIXME: Is there a way around this?
|
||||||
|
SmallVector<OperandBundleDef> OpBundles;
|
||||||
|
OpBundles.reserve(NumOpBundles);
|
||||||
|
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||||
|
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
|
return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
|
||||||
ArrayRef<Value*>(unwrap(Args), NumArgs),
|
ArrayRef<Value*>(unwrap(Args), NumArgs),
|
||||||
ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles),
|
ArrayRef<OperandBundleDef>(OpBundles),
|
||||||
Name));
|
Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1585,7 +1601,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||||
LLVMBasicBlockRef DefaultDest,
|
LLVMBasicBlockRef DefaultDest,
|
||||||
LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
|
LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
|
||||||
LLVMValueRef *Args, unsigned NumArgs,
|
LLVMValueRef *Args, unsigned NumArgs,
|
||||||
OperandBundleDef **OpBundles, unsigned NumOpBundles,
|
OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles,
|
||||||
const char *Name) {
|
const char *Name) {
|
||||||
Value *Callee = unwrap(Fn);
|
Value *Callee = unwrap(Fn);
|
||||||
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
||||||
|
@ -1597,11 +1613,18 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
||||||
IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i]));
|
IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Is there a way around this?
|
||||||
|
SmallVector<OperandBundleDef> OpBundles;
|
||||||
|
OpBundles.reserve(NumOpBundles);
|
||||||
|
for (unsigned i = 0; i < NumOpBundles; ++i) {
|
||||||
|
OpBundles.push_back(*OpBundlesIndirect[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return wrap(unwrap(B)->CreateCallBr(
|
return wrap(unwrap(B)->CreateCallBr(
|
||||||
FTy, Callee, unwrap(DefaultDest),
|
FTy, Callee, unwrap(DefaultDest),
|
||||||
ArrayRef<BasicBlock*>(IndirectDestsUnwrapped),
|
ArrayRef<BasicBlock*>(IndirectDestsUnwrapped),
|
||||||
ArrayRef<Value*>(unwrap(Args), NumArgs),
|
ArrayRef<Value*>(unwrap(Args), NumArgs),
|
||||||
ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles),
|
ArrayRef<OperandBundleDef>(OpBundles),
|
||||||
Name));
|
Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue