authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-05 18:07:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-05 18:07:15-07:00
logb8d17b11a7eba696200ab9b5819121f48ad123d1
tree364b74d0554e4f1d37b9d5d927695e409244cd21
parent094336f07cdf42f2f79df5b190ccc0139412cfbc

add tests for integer overflow crashing

see #46

2 files changed, 79 insertions(+), 31 deletions(-)

src/codegen.cpp+39-31
...@@ -1097,7 +1097,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1097,7 +1097,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1097 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);1097 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
10981098
1099 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");1099 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
1100 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");1100 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1101 LLVMBuildStore(g->builder, len_value, len_field_ptr);1101 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11021102
1103 return tmp_struct_ptr;1103 return tmp_struct_ptr;
...@@ -1115,7 +1115,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1115,7 +1115,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1115 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);1115 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
11161116
1117 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");1117 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
1118 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");1118 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1119 LLVMBuildStore(g->builder, len_value, len_field_ptr);1119 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11201120
1121 return tmp_struct_ptr;1121 return tmp_struct_ptr;
...@@ -1160,7 +1160,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1160,7 +1160,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1160 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);1160 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
11611161
1162 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, len_index, "");1162 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, len_index, "");
1163 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");1163 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1164 LLVMBuildStore(g->builder, len_value, len_field_ptr);1164 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11651165
1166 return tmp_struct_ptr;1166 return tmp_struct_ptr;
...@@ -1287,6 +1287,28 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,...@@ -1287,6 +1287,28 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
1287 return target_ref;1287 return target_ref;
1288}1288}
12891289
1290static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
1291 LLVMValueRef val1, LLVMValueRef val2)
1292{
1293 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
1294 LLVMValueRef params[] = {
1295 val1,
1296 val2,
1297 };
1298 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
1299 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1300 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1301 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
1302 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
1303 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
1304
1305 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1306 gen_debug_safety_crash(g);
1307
1308 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1309 return result;
1310}
1311
1290static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {1312static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1291 assert(node->type == NodeTypePrefixOpExpr);1313 assert(node->type == NodeTypePrefixOpExpr);
1292 assert(node->data.prefix_op_expr.primary_expr);1314 assert(node->data.prefix_op_expr.primary_expr);
...@@ -1300,12 +1322,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1300,12 +1322,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1300 case PrefixOpNegation:1322 case PrefixOpNegation:
1301 {1323 {
1302 LLVMValueRef expr = gen_expr(g, expr_node);1324 LLVMValueRef expr = gen_expr(g, expr_node);
1303 if (expr_type->id == TypeTableEntryIdInt) {1325 set_debug_source_node(g, node);
1304 set_debug_source_node(g, node);1326 if (expr_type->id == TypeTableEntryIdFloat) {
1305 return LLVMBuildNeg(g->builder, expr, "");
1306 } else if (expr_type->id == TypeTableEntryIdFloat) {
1307 set_debug_source_node(g, node);
1308 return LLVMBuildFNeg(g->builder, expr, "");1327 return LLVMBuildFNeg(g->builder, expr, "");
1328 } else if (expr_type->id == TypeTableEntryIdInt) {
1329 if (expr_type->data.integral.is_wrapping) {
1330 return LLVMBuildNeg(g->builder, expr, "");
1331 } else if (want_debug_safety(g, expr_node)) {
1332 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1333 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
1334 } else if (expr_type->data.integral.is_signed) {
1335 return LLVMBuildNSWNeg(g->builder, expr, "");
1336 } else {
1337 return LLVMBuildNUWNeg(g->builder, expr, "");
1338 }
1309 } else {1339 } else {
1310 zig_unreachable();1340 zig_unreachable();
1311 }1341 }
...@@ -1431,28 +1461,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1431,28 +1461,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1431 zig_unreachable();1461 zig_unreachable();
1432}1462}
14331463
1434static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
1435 LLVMValueRef val1, LLVMValueRef val2)
1436{
1437 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
1438 LLVMValueRef params[] = {
1439 val1,
1440 val2,
1441 };
1442 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
1443 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1444 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1445 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
1446 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
1447 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
1448
1449 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1450 gen_debug_safety_crash(g);
1451
1452 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1453 return result;
1454}
1455
1456static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,1464static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1457 LLVMValueRef val1, LLVMValueRef val2,1465 LLVMValueRef val1, LLVMValueRef val2,
1458 TypeTableEntry *op1_type, TypeTableEntry *op2_type,1466 TypeTableEntry *op1_type, TypeTableEntry *op2_type,
...@@ -2727,7 +2735,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {...@@ -2727,7 +2735,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
27272735
2728 LLVMPositionBuilderAtEnd(g->builder, continue_block);2736 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2729 set_debug_source_node(g, node);2737 set_debug_source_node(g, node);
2730 LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, "");2738 LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
2731 LLVMBuildStore(g->builder, new_index_val, index_ptr);2739 LLVMBuildStore(g->builder, new_index_val, index_ptr);
2732 LLVMBuildBr(g->builder, cond_block);2740 LLVMBuildBr(g->builder, cond_block);
27332741
test/run_tests.cpp+40
...@@ -1323,6 +1323,46 @@ fn bar(a: []i32) -> i32 {...@@ -1323,6 +1323,46 @@ fn bar(a: []i32) -> i32 {
1323fn baz(a: i32) {}1323fn baz(a: i32) {}
1324 )SOURCE");1324 )SOURCE");
13251325
1326 add_debug_safety_case("integer addition overflow", R"SOURCE(
1327pub fn main(args: [][]u8) -> %void {
1328 add(65530, 10);
1329}
1330#static_eval_enable(false)
1331fn add(a: u16, b: u16) -> u16 {
1332 a + b
1333}
1334 )SOURCE");
1335
1336 add_debug_safety_case("integer subtraction overflow", R"SOURCE(
1337pub fn main(args: [][]u8) -> %void {
1338 sub(10, 20);
1339}
1340#static_eval_enable(false)
1341fn sub(a: u16, b: u16) -> u16 {
1342 a - b
1343}
1344 )SOURCE");
1345
1346 add_debug_safety_case("integer multiplication overflow", R"SOURCE(
1347pub fn main(args: [][]u8) -> %void {
1348 mul(300, 6000);
1349}
1350#static_eval_enable(false)
1351fn mul(a: u16, b: u16) -> u16 {
1352 a * b
1353}
1354 )SOURCE");
1355
1356 add_debug_safety_case("integer negation overflow", R"SOURCE(
1357pub fn main(args: [][]u8) -> %void {
1358 neg(-32768);
1359}
1360#static_eval_enable(false)
1361fn neg(a: i16) -> i16 {
1362 -a
1363}
1364 )SOURCE");
1365
1326}1366}
13271367
1328//////////////////////////////////////////////////////////////////////////////1368//////////////////////////////////////////////////////////////////////////////