Skip to content

Commit

Permalink
Add debug checks to const gep argument bit sizes to resolve TheDan64#213
Browse files Browse the repository at this point in the history
  • Loading branch information
djozis committed Oct 5, 2020
1 parent 5c4adc1 commit 85f6ecb
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/values/ptr_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,17 @@ impl<'ctx> PointerValue<'ctx> {

// REVIEW: Should this be on array value too?
/// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
/// GEP indexes must be 32 bit integer values. Constant folding may result in other sizes working.
pub unsafe fn const_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
if cfg!(debug_assertions) {
for (index, value) in ordered_indexes.iter().enumerate() {
let bit_width = value.get_type().get_bit_width();
if bit_width != 32 {
panic!("Index #{} in ordered_indexes argument to const_gep call was a {} bit integer instead of 32 bit integer - gep indexes must be i32 values", index, bit_width);
}
}
}

let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter()
.map(|val| val.as_value_ref())
.collect();
Expand All @@ -80,7 +90,17 @@ impl<'ctx> PointerValue<'ctx> {
}

/// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
/// GEP indexes must be 32 bit integer values. Constant folding may result in other sizes working.
pub unsafe fn const_in_bounds_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
if cfg!(debug_assertions) {
for (index, value) in ordered_indexes.iter().enumerate() {
let bit_width = value.get_type().get_bit_width();
if bit_width != 32 {
panic!("Index #{} in ordered_indexes argument to const_in_bounds_gep call was a {} bit integer instead of 32 bit integer - gep indexes must be i32 values", index, bit_width);
}
}
}

let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter()
.map(|val| val.as_value_ref())
.collect();
Expand Down
27 changes: 27 additions & 0 deletions tests/all/test_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1203,3 +1203,30 @@ fn test_constant_expression() {
assert!(expr.is_const());
assert!(!expr.is_constant_int());
}

#[test]
#[should_panic]
fn test_const_gep_i64() {
let context = Context::create();

let i64_type = context.i64_type();
let i64_ptr_type = i64_type.ptr_type(AddressSpace::Generic);
let i64_ptr_null = i64_ptr_type.const_zero();
unsafe {
// i64 indexes are not permitted - should panic.
i64_ptr_null.const_gep(&[i64_type.const_zero()]);
}
}

#[test]
fn test_const_gep_i32() {
let context = Context::create();

let i32_type = context.i32_type();
let i32_ptr_type = i32_type.ptr_type(AddressSpace::Generic);
let i32_ptr_null = i32_ptr_type.const_zero();
unsafe {
// i32 indexes are permitted.
i32_ptr_null.const_gep(&[i32_type.const_zero()]);
}
}

0 comments on commit 85f6ecb

Please sign in to comment.