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) {
10971097 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
10981098
10991099 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, "");
11011101 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11021102
11031103 return tmp_struct_ptr;
......@@ -1115,7 +1115,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
11151115 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
11161116
11171117 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, "");
11191119 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11201120
11211121 return tmp_struct_ptr;
......@@ -1160,7 +1160,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
11601160 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
11611161
11621162 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, "");
11641164 LLVMBuildStore(g->builder, len_value, len_field_ptr);
11651165
11661166 return tmp_struct_ptr;
......@@ -1287,6 +1287,28 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
12871287 return target_ref;
12881288}
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
12901312static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
12911313 assert(node->type == NodeTypePrefixOpExpr);
12921314 assert(node->data.prefix_op_expr.primary_expr);
......@@ -1300,12 +1322,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
13001322 case PrefixOpNegation:
13011323 {
13021324 LLVMValueRef expr = gen_expr(g, expr_node);
1303 if (expr_type->id == TypeTableEntryIdInt) {
1304 set_debug_source_node(g, node);
1305 return LLVMBuildNeg(g->builder, expr, "");
1306 } else if (expr_type->id == TypeTableEntryIdFloat) {
1307 set_debug_source_node(g, node);
1325 set_debug_source_node(g, node);
1326 if (expr_type->id == TypeTableEntryIdFloat) {
13081327 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 }
13091339 } else {
13101340 zig_unreachable();
13111341 }
......@@ -1431,28 +1461,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
14311461 zig_unreachable();
14321462}
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
14561464static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
14571465 LLVMValueRef val1, LLVMValueRef val2,
14581466 TypeTableEntry *op1_type, TypeTableEntry *op2_type,
......@@ -2727,7 +2735,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
27272735
27282736 LLVMPositionBuilderAtEnd(g->builder, continue_block);
27292737 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, "");
27312739 LLVMBuildStore(g->builder, new_index_val, index_ptr);
27322740 LLVMBuildBr(g->builder, cond_block);
27332741
test/run_tests.cpp+40
......@@ -1323,6 +1323,46 @@ fn bar(a: []i32) -> i32 {
13231323fn baz(a: i32) {}
13241324 )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
13261366}
13271367
13281368//////////////////////////////////////////////////////////////////////////////