Skip to content

Commit 87a3dc2

Browse files
committed
Added bounds checking to build_insert_value
1 parent 7763b6a commit 87a3dc2

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

src/builder.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use llvm_sys::{LLVMTypeKind, LLVMAtomicOrdering};
55

66
use {IntPredicate, FloatPredicate};
77
use basic_block::BasicBlock;
8-
use values::{AggregateValue, AsValueRef, BasicValue, BasicValueEnum, PhiValue, FunctionValue, IntValue, PointerValue, VectorValue, InstructionValue, GlobalValue, IntMathValue, FloatMathValue, PointerMathValue, InstructionOpcode, CallSiteValue};
8+
use values::{AggregateValue, AggregateValueEnum, AsValueRef, BasicValue, BasicValueEnum, PhiValue, FunctionValue, IntValue, PointerValue, VectorValue, InstructionValue, GlobalValue, IntMathValue, FloatMathValue, PointerMathValue, InstructionOpcode, CallSiteValue};
99
use types::{AsTypeRef, BasicType, IntMathType, FloatMathType, PointerType, PointerMathType};
1010

1111
use std::ffi::CString;
@@ -947,7 +947,6 @@ impl Builder {
947947

948948
// REVIEW: How does LLVM treat out of bound index? Maybe we should return an Option?
949949
// or is that only in bounds GEP
950-
// REVIEW: Should this be AggregatePointerValue?
951950
pub fn build_extract_value<AV: AggregateValue>(&self, value: AV, index: u32, name: &str) -> BasicValueEnum {
952951
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
953952

@@ -986,22 +985,32 @@ impl Builder {
986985
/// let const_int2 = i32_type.const_int(5, false);
987986
/// let const_int3 = i32_type.const_int(6, false);
988987
///
989-
/// builder.build_insert_value(array, const_int1, 0, "insert");
990-
/// builder.build_insert_value(array, const_int2, 1, "insert");
991-
/// builder.build_insert_value(array, const_int3, 2, "insert");
988+
/// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_some());
989+
/// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_some());
990+
/// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_some());
991+
/// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none());
992992
/// ```
993-
pub fn build_insert_value<AV, BV>(&self, agg: AV, value: BV, index: u32, name: &str) -> InstructionValue
993+
pub fn build_insert_value<AV, BV>(&self, agg: AV, value: BV, index: u32, name: &str) -> Option<InstructionValue>
994994
where
995995
AV: AggregateValue,
996996
BV: BasicValue,
997997
{
998+
let size = match agg.as_aggregate_value_enum() {
999+
AggregateValueEnum::ArrayValue(av) => av.get_type().len(),
1000+
AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(),
1001+
};
1002+
1003+
if index >= size {
1004+
return None;
1005+
}
1006+
9981007
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
9991008

10001009
let value = unsafe {
10011010
LLVMBuildInsertValue(self.builder, agg.as_value_ref(), value.as_value_ref(), index, c_string.as_ptr())
10021011
};
10031012

1004-
InstructionValue::new(value)
1013+
Some(InstructionValue::new(value))
10051014
}
10061015

10071016
pub fn build_extract_element(&self, vector: VectorValue, index: IntValue, name: &str) -> BasicValueEnum {

tests/all/test_builder.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -624,15 +624,19 @@ fn test_insert_value() {
624624
let const_int3 = i32_type.const_int(6, false);
625625
let const_float = f32_type.const_float(3.14);
626626

627-
builder.build_insert_value(array, const_int1, 0, "insert");
628-
builder.build_insert_value(array, const_int2, 1, "insert");
629-
builder.build_insert_value(array, const_int3, 2, "insert");
627+
assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_some());
628+
assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_some());
629+
assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_some());
630+
assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none());
631+
assert!(builder.build_insert_value(array, const_int3, 4, "insert").is_none());
630632

631633
let struct_alloca = builder.build_alloca(struct_type, "struct_alloca");
632634
let struct_value = builder.build_load(struct_alloca, "struct_load").into_struct_value();
633635

634-
builder.build_insert_value(struct_value, const_int2, 0, "insert");
635-
builder.build_insert_value(struct_value, const_float, 1, "insert");
636+
assert!(builder.build_insert_value(struct_value, const_int2, 0, "insert").is_some());
637+
assert!(builder.build_insert_value(struct_value, const_float, 1, "insert").is_some());
638+
assert!(builder.build_insert_value(struct_value, const_float, 2, "insert").is_none());
639+
assert!(builder.build_insert_value(struct_value, const_float, 3, "insert").is_none());
636640

637641
builder.build_return(None);
638642

0 commit comments

Comments
 (0)