Rollup merge of #122000 - erer1243:issue-121868, r=nikic
Fix 32-bit overflows in LLVM composite constants Inspired by #121868. Fixes unsoundness created when constructing constant arrays, strings, and structs with 2^32 or more elements on x86_64. This introduces copies of a few LLVM functions that have their signatures updated to use size_t in place of unsigned int. Alternatively we could just add overflow checks and just disallow huge composite constants. That introduces less code, but maybe a huge static block of memory is useful in embedded/no-os situations?
This commit is contained in:
commit
60f4b7a56e
4 changed files with 52 additions and 30 deletions
|
@ -95,11 +95,13 @@ impl<'ll> BackendTypes for CodegenCx<'ll, '_> {
|
|||
|
||||
impl<'ll> CodegenCx<'ll, '_> {
|
||||
pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
||||
unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) }
|
||||
let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow");
|
||||
unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) }
|
||||
}
|
||||
|
||||
pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
|
||||
unsafe { llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint) }
|
||||
let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow");
|
||||
unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) }
|
||||
}
|
||||
|
||||
pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
|
||||
|
@ -108,8 +110,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
|
||||
unsafe {
|
||||
assert_eq!(idx as c_uint as u64, idx);
|
||||
let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap();
|
||||
let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow");
|
||||
let r = llvm::LLVMGetAggregateElement(v, idx).unwrap();
|
||||
|
||||
debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r);
|
||||
|
||||
|
@ -329,7 +331,7 @@ pub fn val_ty(v: &Value) -> &Type {
|
|||
pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
||||
unsafe {
|
||||
let ptr = bytes.as_ptr() as *const c_char;
|
||||
llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True)
|
||||
llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,9 +340,8 @@ pub fn struct_in_context<'ll>(
|
|||
elts: &[&'ll Value],
|
||||
packed: bool,
|
||||
) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, packed as Bool)
|
||||
}
|
||||
let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
|
||||
unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -936,10 +936,16 @@ extern "C" {
|
|||
pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
|
||||
|
||||
// Operations on composite constants
|
||||
pub fn LLVMConstStringInContext(
|
||||
pub fn LLVMConstArray2<'a>(
|
||||
ElementTy: &'a Type,
|
||||
ConstantVals: *const &'a Value,
|
||||
Length: u64,
|
||||
) -> &'a Value;
|
||||
pub fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type;
|
||||
pub fn LLVMConstStringInContext2(
|
||||
C: &Context,
|
||||
Str: *const c_char,
|
||||
Length: c_uint,
|
||||
Length: size_t,
|
||||
DontNullTerminate: Bool,
|
||||
) -> &Value;
|
||||
pub fn LLVMConstStructInContext<'a>(
|
||||
|
@ -948,14 +954,6 @@ extern "C" {
|
|||
Count: c_uint,
|
||||
Packed: Bool,
|
||||
) -> &'a Value;
|
||||
|
||||
// FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17
|
||||
// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc
|
||||
pub fn LLVMConstArray<'a>(
|
||||
ElementTy: &'a Type,
|
||||
ConstantVals: *const &'a Value,
|
||||
Length: c_uint,
|
||||
) -> &'a Value;
|
||||
pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
|
||||
|
||||
// Constant expressions
|
||||
|
@ -1530,9 +1528,6 @@ extern "C" {
|
|||
/// See llvm::LLVMTypeKind::getTypeID.
|
||||
pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
|
||||
|
||||
// Operations on array, pointer, and vector types (sequence types)
|
||||
pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type;
|
||||
|
||||
// Operations on all values
|
||||
pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
|
||||
pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
|
||||
|
|
|
@ -233,7 +233,7 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
|
||||
fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
|
||||
unsafe { llvm::LLVMRustArrayType(ty, len) }
|
||||
unsafe { llvm::LLVMArrayType2(ty, len) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue