diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 67a2f5740..880d97b3f 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -69,6 +69,7 @@ public: Unreachable = 0, IncorrectCallIndirectSignature = 1, MemoryOutOfBounds = 2, + CallIndirectOOB = 3, Unknown, }; diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 46ddffa41..341848d27 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -744,6 +744,54 @@ fn parse_function( ) }; + let truncated_table_bounds = builder.build_int_truncate( + table_bound, + intrinsics.i32_ty, + "truncated_table_bounds", + ); + + // First, check if the index is outside of the table bounds. + let index_in_bounds = builder.build_int_compare( + IntPredicate::ULT, + func_index, + truncated_table_bounds, + "index_in_bounds", + ); + + let index_in_bounds = builder + .build_call( + intrinsics.expect_i1, + &[ + index_in_bounds.as_basic_value_enum(), + intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(), + ], + "index_in_bounds_expect", + ) + .try_as_basic_value() + .left() + .unwrap() + .into_int_value(); + + let in_bounds_continue_block = + context.append_basic_block(&function, "in_bounds_continue_block"); + let not_in_bounds_block = + context.append_basic_block(&function, "not_in_bounds_block"); + builder.build_conditional_branch( + index_in_bounds, + &in_bounds_continue_block, + ¬_in_bounds_block, + ); + builder.position_at_end(¬_in_bounds_block); + builder.build_call( + intrinsics.throw_trap, + &[intrinsics.trap_call_indirect_oob], + "throw", + ); + builder.build_unreachable(); + builder.position_at_end(&in_bounds_continue_block); + + // Next, check if the signature id is correct. + let sigindices_equal = builder.build_int_compare( IntPredicate::EQ, expected_dynamic_sigindex, diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 908448a51..f19561417 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -95,6 +95,7 @@ pub struct Intrinsics { pub trap_unreachable: BasicValueEnum, pub trap_call_indirect_sig: BasicValueEnum, + pub trap_call_indirect_oob: BasicValueEnum, pub trap_memory_oob: BasicValueEnum, // VM intrinsics. @@ -293,6 +294,7 @@ impl Intrinsics { trap_unreachable: i32_zero.as_basic_value_enum(), trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), + trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(), trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(), // VM intrinsics.