authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 15:02:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 15:02:22-07:00
loga180168871b6e32a8c0825b1eb309587c3e0d179
tree935616676906c2b56d3d19f8acd6a07e86865e14
parent2bf6c28bc3e535deb651d5b37e332226e0d38930

fix division by 0 crashing compiler

closes #99 closes #124 thanks to Michael Patraw for submitting a patch for this.

2 files changed, 50 insertions(+), 1 deletions(-)

src/analyze.cpp+30-1
...@@ -2929,6 +2929,27 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -2929,6 +2929,27 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
2929 return resolved_type;2929 return resolved_type;
2930 }2930 }
29312931
2932 bool is_int = false;
2933 bool is_float = false;
2934 if (resolved_type->id == TypeTableEntryIdInt ||
2935 resolved_type->id == TypeTableEntryIdNumLitInt)
2936 {
2937 is_int = true;
2938 } else if ((resolved_type->id == TypeTableEntryIdFloat ||
2939 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
2940 (bin_op_type == BinOpTypeAdd ||
2941 bin_op_type == BinOpTypeSub ||
2942 bin_op_type == BinOpTypeMult ||
2943 bin_op_type == BinOpTypeDiv ||
2944 bin_op_type == BinOpTypeMod))
2945 {
2946 is_float = true;
2947 } else {
2948 add_node_error(g, node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
2949 buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name)));
2950 return g->builtin_types.entry_invalid;
2951 }
2952
2932 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;2953 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
2933 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;2954 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
2934 if (!op1_val->ok || !op2_val->ok) {2955 if (!op1_val->ok || !op2_val->ok) {
...@@ -2942,7 +2963,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -2942,7 +2963,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
2942 } else if (bin_op_type == BinOpTypeMult) {2963 } else if (bin_op_type == BinOpTypeMult) {
2943 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, *op1, *op2, resolved_type);2964 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, *op1, *op2, resolved_type);
2944 } else if (bin_op_type == BinOpTypeDiv) {2965 } else if (bin_op_type == BinOpTypeDiv) {
2945 return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);2966 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
2967 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
2968 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
2969 {
2970 add_node_error(g, node, buf_sprintf("division by zero is undefined"));
2971 return g->builtin_types.entry_invalid;
2972 } else {
2973 return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);
2974 }
2946 } else if (bin_op_type == BinOpTypeMod) {2975 } else if (bin_op_type == BinOpTypeMod) {
2947 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, *op1, *op2, resolved_type);2976 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, *op1, *op2, resolved_type);
2948 } else if (bin_op_type == BinOpTypeBinOr) {2977 } else if (bin_op_type == BinOpTypeBinOr) {
test/run_tests.cpp+20
...@@ -1740,6 +1740,26 @@ fn f() {...@@ -1740,6 +1740,26 @@ fn f() {
1740 if (true) { }1740 if (true) { }
1741}1741}
1742 )SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement");1742 )SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement");
1743
1744
1745 add_compile_fail_case("addition with non numbers", R"SOURCE(
1746struct Foo {
1747 field: i32,
1748}
1749const x = Foo {.field = 1} + Foo {.field = 2};
1750 )SOURCE", 1, ".tmp_source.zig:5:28: error: invalid operands to binary expression: 'Foo' and 'Foo'");
1751
1752
1753 add_compile_fail_case("division by zero", R"SOURCE(
1754const lit_int_x = 1 / 0;
1755const lit_float_x = 1.0 / 0.0;
1756const int_x = i32(1) / i32(0);
1757const float_x = f32(1.0) / f32(0.0);
1758 )SOURCE", 4,
1759 ".tmp_source.zig:2:21: error: division by zero is undefined",
1760 ".tmp_source.zig:3:25: error: division by zero is undefined",
1761 ".tmp_source.zig:4:22: error: division by zero is undefined",
1762 ".tmp_source.zig:5:26: error: division by zero is undefined");
1743}1763}
17441764
1745//////////////////////////////////////////////////////////////////////////////1765//////////////////////////////////////////////////////////////////////////////