From c4e76e6a5950f619781976925801f231ffe4455b Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 11 Dec 2020 11:44:07 +0800 Subject: [PATCH] checker: check div/mod by zero (#7256) --- vlib/v/checker/checker.v | 37 ++++++++++------- .../tests/div_mod_by_cast_zero_int_err.out | 40 +++++++++++++++++++ .../tests/div_mod_by_cast_zero_int_err.vv | 10 +++++ .../tests/division_by_cast_zero_float_err.out | 12 ++++++ .../tests/division_by_cast_zero_float_err.vv | 4 ++ 5 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 vlib/v/checker/tests/div_mod_by_cast_zero_int_err.out create mode 100644 vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv create mode 100644 vlib/v/checker/tests/division_by_cast_zero_float_err.out create mode 100644 vlib/v/checker/tests/division_by_cast_zero_float_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 36ac24d7d8..0cd0ef2c23 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -609,6 +609,27 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { return struct_init.typ } +fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) { + match mut expr { + ast.FloatLiteral { + if expr.val.f64() == 0.0 { + oper := if op_kind == .div { 'division' } else { 'modulo' } + c.error('$oper by zero', expr.pos) + } + } + ast.IntegerLiteral { + if expr.val.int() == 0 { + oper := if op_kind == .div { 'division' } else { 'modulo' } + c.error('$oper by zero', expr.pos) + } + } + ast.CastExpr { + c.check_div_mod_by_zero(expr.expr, op_kind) + } + else {} + } +} + pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { // println('checker: infix expr(op $infix_expr.op.str())') former_expected_type := c.expected_type @@ -757,21 +778,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } } if infix_expr.op in [.div, .mod] { - match mut infix_expr.right { - ast.FloatLiteral { - if infix_expr.right.val.f64() == 0.0 { - oper := if infix_expr.op == .div { 'division' } else { 'modulo' } - c.error('$oper by zero', infix_expr.right.pos) - } - } - ast.IntegerLiteral { - if infix_expr.right.val.int() == 0 { - oper := if infix_expr.op == .div { 'division' } else { 'modulo' } - c.error('$oper by zero', infix_expr.right.pos) - } - } - else {} - } + c.check_div_mod_by_zero(infix_expr.right, infix_expr.op) } return_type = promoted_type } diff --git a/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.out b/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.out new file mode 100644 index 0000000000..b29d963f18 --- /dev/null +++ b/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.out @@ -0,0 +1,40 @@ +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:2:21: error: division by zero + 1 | fn main() { + 2 | println(u64(1)/u64(0)) + | ^ + 3 | println(u64(1)%u64(0)) + 4 | +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:3:21: error: modulo by zero + 1 | fn main() { + 2 | println(u64(1)/u64(0)) + 3 | println(u64(1)%u64(0)) + | ^ + 4 | + 5 | println(u32(1)/u32(0x0)) +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:5:21: error: division by zero + 3 | println(u64(1)%u64(0)) + 4 | + 5 | println(u32(1)/u32(0x0)) + | ~~~ + 6 | println(u32(1)%u32(0x0)) + 7 | +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:6:21: error: modulo by zero + 4 | + 5 | println(u32(1)/u32(0x0)) + 6 | println(u32(1)%u32(0x0)) + | ~~~ + 7 | + 8 | println(u16(1)/u16(0b0)) +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:8:21: error: division by zero + 6 | println(u32(1)%u32(0x0)) + 7 | + 8 | println(u16(1)/u16(0b0)) + | ~~~ + 9 | println(u16(1)%u16(0b0)) + 10 | } +vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:9:21: error: modulo by zero + 7 | + 8 | println(u16(1)/u16(0b0)) + 9 | println(u16(1)%u16(0b0)) + | ~~~ + 10 | } diff --git a/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv b/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv new file mode 100644 index 0000000000..215ae9e398 --- /dev/null +++ b/vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv @@ -0,0 +1,10 @@ +fn main() { + println(u64(1)/u64(0)) + println(u64(1)%u64(0)) + + println(u32(1)/u32(0x0)) + println(u32(1)%u32(0x0)) + + println(u16(1)/u16(0b0)) + println(u16(1)%u16(0b0)) +} diff --git a/vlib/v/checker/tests/division_by_cast_zero_float_err.out b/vlib/v/checker/tests/division_by_cast_zero_float_err.out new file mode 100644 index 0000000000..f6bbda23dc --- /dev/null +++ b/vlib/v/checker/tests/division_by_cast_zero_float_err.out @@ -0,0 +1,12 @@ +vlib/v/checker/tests/division_by_cast_zero_float_err.vv:2:23: error: division by zero + 1 | fn main() { + 2 | println(f32(1.0)/f32(0.0)) + | ~~~ + 3 | println(f64(1.0)/f64(0.0)) + 4 | } +vlib/v/checker/tests/division_by_cast_zero_float_err.vv:3:23: error: division by zero + 1 | fn main() { + 2 | println(f32(1.0)/f32(0.0)) + 3 | println(f64(1.0)/f64(0.0)) + | ~~~ + 4 | } diff --git a/vlib/v/checker/tests/division_by_cast_zero_float_err.vv b/vlib/v/checker/tests/division_by_cast_zero_float_err.vv new file mode 100644 index 0000000000..6feee15a47 --- /dev/null +++ b/vlib/v/checker/tests/division_by_cast_zero_float_err.vv @@ -0,0 +1,4 @@ +fn main() { + println(f32(1.0)/f32(0.0)) + println(f64(1.0)/f64(0.0)) +}