From 63d37b7cff0907cdf2361f1d61f19410fd6cc626 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 14 Feb 2017 01:08:30 -0500 Subject: add runtime debug safety for dividing integer min value by -1 closes #260 --- src/codegen.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index b98d549e84..df4b6fcf7c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -846,14 +846,30 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val } else { zig_unreachable(); } - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); - LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block); + LLVMBasicBlockRef div_zero_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); + LLVMBasicBlockRef div_zero_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); + LLVMBuildCondBr(g->builder, is_zero_bit, div_zero_fail_block, div_zero_ok_block); - LLVMPositionBuilderAtEnd(g->builder, fail_block); + LLVMPositionBuilderAtEnd(g->builder, div_zero_fail_block); gen_debug_safety_crash(g, PanicMsgIdDivisionByZero); - LLVMPositionBuilderAtEnd(g->builder, ok_block); + LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block); + + if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) { + LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true); + LLVMValueRef int_min_value = LLVMConstInt(type_entry->type_ref, min_signed_val(type_entry), true); + LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk"); + LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail"); + LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, ""); + LLVMValueRef den_is_neg_1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, neg_1_value, ""); + LLVMValueRef overflow_fail_bit = LLVMBuildAnd(g->builder, num_is_int_min, den_is_neg_1, ""); + LLVMBuildCondBr(g->builder, overflow_fail_bit, overflow_fail_block, overflow_ok_block); + + LLVMPositionBuilderAtEnd(g->builder, overflow_fail_block); + gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); + + LLVMPositionBuilderAtEnd(g->builder, overflow_ok_block); + } } if (type_entry->id == TypeTableEntryIdFloat) { -- cgit v1.2.3