From 85f6ecb8f51cf6898df689807236ae55b1633d0e Mon Sep 17 00:00:00 2001 From: David Jozis Date: Mon, 5 Oct 2020 17:45:54 -0400 Subject: [PATCH] Add debug checks to const gep argument bit sizes to resolve #213 --- src/values/ptr_value.rs | 20 ++++++++++++++++++++ tests/all/test_values.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/values/ptr_value.rs b/src/values/ptr_value.rs index c136ba8d0ff..7b96e2083ce 100644 --- a/src/values/ptr_value.rs +++ b/src/values/ptr_value.rs @@ -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 = ordered_indexes.iter() .map(|val| val.as_value_ref()) .collect(); @@ -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 = ordered_indexes.iter() .map(|val| val.as_value_ref()) .collect(); diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index b7dce5f160e..56347b672e8 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -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()]); + } +}