From 900ec70711efd1298d4c77d7cab7438085eabd72 Mon Sep 17 00:00:00 2001 From: Pierre Curto Date: Wed, 24 Jan 2024 17:36:39 +0100 Subject: [PATCH] checker: add cast overflow checks (#20641) --- vlib/math/big/array_ops_test.v | 8 ++--- vlib/strconv/f32_str.c.v | 2 -- vlib/v/checker/checker.v | 28 +++++++++++++++ .../tests/cast_integer_with_overflow_err.out | 34 +++++++++++++++++++ .../tests/cast_integer_with_overflow_err.vv | 10 ++++++ 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 vlib/v/checker/tests/cast_integer_with_overflow_err.out create mode 100644 vlib/v/checker/tests/cast_integer_with_overflow_err.vv diff --git a/vlib/math/big/array_ops_test.v b/vlib/math/big/array_ops_test.v index 813fe31e9..40d0bc5cf 100644 --- a/vlib/math/big/array_ops_test.v +++ b/vlib/math/big/array_ops_test.v @@ -198,13 +198,13 @@ fn test_left_and_right_shift() { shift_digits_left(r, 1, mut r) assert r == b - mut c := [u32(0xffffffff)] + mut c := [u32(0xffff_ffff)] shift_digits_left(c, 16, mut c) - assert c == [u32(0xfffff0000), 0xffff] + assert c == [u32(0xffff_0000), 0xffff] shift_digits_right(c, 8, mut c) - assert c == [u32(0xfffffff00), 0xff] + assert c == [u32(0xffff_ff00), 0xff] shift_digits_right(c, 16, mut c) - assert c == [u32(0x00ffffff)] + assert c == [u32(0x00ff_ffff)] shift_digits_right(c, 16, mut c) assert c == [u32(0xff)] shift_digits_right(c, 16, mut c) diff --git a/vlib/strconv/f32_str.c.v b/vlib/strconv/f32_str.c.v index 72c69778b..e9dfde378 100644 --- a/vlib/strconv/f32_str.c.v +++ b/vlib/strconv/f32_str.c.v @@ -32,8 +32,6 @@ const ten_pow_table_32 = [ u32(10000000), u32(100000000), u32(1000000000), - u32(10000000000), - u32(100000000000), ]! //============================================================================= diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ca567a255..f8d641493 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3,6 +3,7 @@ module checker import os +import strconv import v.ast import v.vmod import v.token @@ -3292,6 +3293,33 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } c.error(error_msg, node.pos) } + } else if to_type.is_int() && mut node.expr is ast.IntegerLiteral { + tt := c.table.type_to_str(to_type) + tsize, _ := c.table.type_size(to_type.idx()) + bit_size := tsize * 8 + value_string := match node.expr.val[0] { + `-`, `+` { + node.expr.val[1..] + } + else { + node.expr.val + } + } + _, e := strconv.common_parse_uint2(value_string, 0, bit_size) + match e { + 0 {} + -3 { + c.error('value `${node.expr.val}` overflows `${tt}`', node.pos) + } + else { + c.error('cannot cast value `${node.expr.val}` to `${tt}`', node.pos) + } + } + } else if to_type.is_float() && mut node.expr is ast.FloatLiteral { + tt := c.table.type_to_str(to_type) + strconv.atof64(node.expr.val) or { + c.error('cannot cast value `${node.expr.val}` to `${tt}`', node.pos) + } } if from_sym.language == .v && !from_type.is_ptr() && final_from_sym.kind in [.sum_type, .interface_] diff --git a/vlib/v/checker/tests/cast_integer_with_overflow_err.out b/vlib/v/checker/tests/cast_integer_with_overflow_err.out new file mode 100644 index 000000000..482a31124 --- /dev/null +++ b/vlib/v/checker/tests/cast_integer_with_overflow_err.out @@ -0,0 +1,34 @@ +vlib/v/checker/tests/cast_integer_with_overflow_err.vv:2:7: error: value `300` overflows `u8` + 1 | fn main() { + 2 | a := u8(300) + | ~~~~~~~ + 3 | _ = a + 4 | b := u16(300_000) +vlib/v/checker/tests/cast_integer_with_overflow_err.vv:4:7: error: value `300000` overflows `u16` + 2 | a := u8(300) + 3 | _ = a + 4 | b := u16(300_000) + | ~~~~~~~~~~~~ + 5 | _ = b + 6 | c := u32(300_000_000_000) +vlib/v/checker/tests/cast_integer_with_overflow_err.vv:6:7: error: value `300000000000` overflows `u32` + 4 | b := u16(300_000) + 5 | _ = b + 6 | c := u32(300_000_000_000) + | ~~~~~~~~~~~~~~~~~~~~ + 7 | _ = c + 8 | d := u64(300_000_000_000_000_000_000) +vlib/v/checker/tests/cast_integer_with_overflow_err.vv:8:17: error: integer literal 300000000000000000000 overflows int + 6 | c := u32(300_000_000_000) + 7 | _ = c + 8 | d := u64(300_000_000_000_000_000_000) + | ~~~~~~~~~~~~~~~~~~~~~ + 9 | _ = d + 10 | } +vlib/v/checker/tests/cast_integer_with_overflow_err.vv:8:7: error: value `300000000000000000000` overflows `u64` + 6 | c := u32(300_000_000_000) + 7 | _ = c + 8 | d := u64(300_000_000_000_000_000_000) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 9 | _ = d + 10 | } diff --git a/vlib/v/checker/tests/cast_integer_with_overflow_err.vv b/vlib/v/checker/tests/cast_integer_with_overflow_err.vv new file mode 100644 index 000000000..cc56ea5a8 --- /dev/null +++ b/vlib/v/checker/tests/cast_integer_with_overflow_err.vv @@ -0,0 +1,10 @@ +fn main() { + a := u8(300) + _ = a + b := u16(300_000) + _ = b + c := u32(300_000_000_000) + _ = c + d := u64(300_000_000_000_000_000_000) + _ = d +} -- 2.39.5