From 5086fd537c38706d093b934f1796d7c0473bf9e2 Mon Sep 17 00:00:00 2001 From: Henrixounez <30901439+Henrixounez@users.noreply.github.com> Date: Sun, 20 Sep 2020 16:29:01 +0200 Subject: [PATCH] checker: prompt error on implicit int overflow by literal (#6410) --- vlib/builtin/int_test.v | 3 --- vlib/rand/mt19937/mt19937_test.v | 4 +-- vlib/rand/musl/musl_rng_test.v | 4 +-- vlib/rand/pcg32/pcg32_test.v | 4 +-- vlib/rand/random_numbers_test.v | 4 +-- vlib/rand/splitmix64/splitmix64_test.v | 4 +-- vlib/rand/sys/system_rng_test.v | 4 +-- vlib/rand/wyrand/wyrand_test.v | 4 +-- vlib/v/checker/checker.v | 31 ++++++++++++++++++++--- vlib/v/checker/tests/overflow_int_err.out | 14 ++++++++++ vlib/v/checker/tests/overflow_int_err.vv | 10 ++++++++ 11 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 vlib/v/checker/tests/overflow_int_err.out create mode 100644 vlib/v/checker/tests/overflow_int_err.vv diff --git a/vlib/builtin/int_test.v b/vlib/builtin/int_test.v index 8650bc747f..f365005eab 100644 --- a/vlib/builtin/int_test.v +++ b/vlib/builtin/int_test.v @@ -182,10 +182,7 @@ fn test_int_decl() { assert typeof(x3) == 'int' assert typeof(x4) == 'int' assert typeof(x5) == 'int' - // integers are always 'int' by default - x6 := 989898932113111 x7 := u64(-321314588900011) - assert typeof(x6) == 'int' assert typeof(x7) == 'u64' } diff --git a/vlib/rand/mt19937/mt19937_test.v b/vlib/rand/mt19937/mt19937_test.v index 22076bb648..0eaa4f9cc9 100644 --- a/vlib/rand/mt19937/mt19937_test.v +++ b/vlib/rand/mt19937/mt19937_test.v @@ -178,8 +178,8 @@ fn test_mt19937_u64_in_range() { } fn test_mt19937_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { mut rng := mt19937.MT19937RNG{} rng.seed(seed) diff --git a/vlib/rand/musl/musl_rng_test.v b/vlib/rand/musl/musl_rng_test.v index 190eb20358..16ec6bb9d5 100644 --- a/vlib/rand/musl/musl_rng_test.v +++ b/vlib/rand/musl/musl_rng_test.v @@ -168,8 +168,8 @@ fn test_musl_u64_in_range() { } fn test_musl_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { mut rng := musl.MuslRNG{} rng.seed(seed) diff --git a/vlib/rand/pcg32/pcg32_test.v b/vlib/rand/pcg32/pcg32_test.v index fc5e97abf6..9c398fd36a 100644 --- a/vlib/rand/pcg32/pcg32_test.v +++ b/vlib/rand/pcg32/pcg32_test.v @@ -169,8 +169,8 @@ fn test_pcg32_u64_in_range() { } fn test_pcg32_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { mut rng := pcg32.PCG32RNG{} rng.seed(seed) diff --git a/vlib/rand/random_numbers_test.v b/vlib/rand/random_numbers_test.v index 6d6e5506ad..18ce5c5f48 100644 --- a/vlib/rand/random_numbers_test.v +++ b/vlib/rand/random_numbers_test.v @@ -100,8 +100,8 @@ fn test_rand_i64_in_range() { } fn test_rand_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for _ in 0 .. rnd_count { value := rand.int31() assert value >= 0 diff --git a/vlib/rand/splitmix64/splitmix64_test.v b/vlib/rand/splitmix64/splitmix64_test.v index f75564b256..2edfe86059 100644 --- a/vlib/rand/splitmix64/splitmix64_test.v +++ b/vlib/rand/splitmix64/splitmix64_test.v @@ -168,8 +168,8 @@ fn test_splitmix64_u64_in_range() { } fn test_splitmix64_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { mut rng := splitmix64.SplitMix64RNG{} rng.seed(seed) diff --git a/vlib/rand/sys/system_rng_test.v b/vlib/rand/sys/system_rng_test.v index d6c2cacea0..b220fe2b23 100644 --- a/vlib/rand/sys/system_rng_test.v +++ b/vlib/rand/sys/system_rng_test.v @@ -237,8 +237,8 @@ fn test_sys_rng_i64_in_range() { } fn test_sys_rng_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { seed_data := [seed] mut rng := sys.SysRNG{} diff --git a/vlib/rand/wyrand/wyrand_test.v b/vlib/rand/wyrand/wyrand_test.v index d36190f8d7..c963c8db81 100644 --- a/vlib/rand/wyrand/wyrand_test.v +++ b/vlib/rand/wyrand/wyrand_test.v @@ -168,8 +168,8 @@ fn test_wyrand_u64_in_range() { } fn test_wyrand_int31() { - max_u31 := 0x7FFFFFFF - sign_mask := 0x80000000 + max_u31 := int(0x7FFFFFFF) + sign_mask := int(0x80000000) for seed in seeds { mut rng := wyrand.WyRandRNG{} rng.seed(seed) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 906d34592e..f88327a292 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -12,8 +12,8 @@ import v.errors const ( max_nr_errors = 300 match_exhaustive_cutoff_limit = 10 - enum_min = int(0x80000000) - enum_max = 0x7FFFFFFF + int_min = int(0x80000000) + int_max = 0x7FFFFFFF ) const ( @@ -1682,7 +1682,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) { match field.expr as field_expr { ast.IntegerLiteral { val := field_expr.val.i64() - if val < enum_min || val > enum_max { + if val < int_min || val > int_max { c.error('enum value `$val` overflows int', field_expr.pos) } else if !decl.is_multi_allowed && int(val) in seen { c.error('enum value `$val` already exists', field_expr.pos) @@ -1707,7 +1707,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) { } else { if seen.len > 0 { last := seen[seen.len - 1] - if last == enum_max { + if last == int_max { c.error('enum value overflows', field.pos) } seen << last + 1 @@ -1805,6 +1805,29 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { right_type := assign_stmt.right_types[i] if is_decl { left_type = c.table.mktyp(right_type) + if left_type == table.int_type { + mut expr := right + mut negative := false + if right is ast.PrefixExpr { + expr = right.right + if right.op == .minus { + negative = true + } + } + if expr is ast.IntegerLiteral { + mut is_large := false + if expr.val.len > 8 { + val := expr.val.i64() + if (!negative && val > int_max) || (negative && -val < int_min) { + is_large = true + } + } + if is_large { + c.error('overflow in implicit type `int`, use explicit type casting instead', + expr.pos) + } + } + } // we are unwrapping here instead if check_expr_opt_call currently if left_type.has_flag(.optional) { left_type = left_type.clear_flag(.optional) diff --git a/vlib/v/checker/tests/overflow_int_err.out b/vlib/v/checker/tests/overflow_int_err.out new file mode 100644 index 0000000000..258aba5fe3 --- /dev/null +++ b/vlib/v/checker/tests/overflow_int_err.out @@ -0,0 +1,14 @@ +vlib/v/checker/tests/overflow_int_err.vv:4:8: error: overflow in implicit type `int`, use explicit type casting instead + 2 | a := -2147483648 + 3 | b := 2147483647 + 4 | c := -2147483649 + | ~~~~~~~~~~ + 5 | d := 2147483648 + 6 | println(a) +vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead + 3 | b := 2147483647 + 4 | c := -2147483649 + 5 | d := 2147483648 + | ~~~~~~~~~~ + 6 | println(a) + 7 | println(b) diff --git a/vlib/v/checker/tests/overflow_int_err.vv b/vlib/v/checker/tests/overflow_int_err.vv new file mode 100644 index 0000000000..0537ae3f55 --- /dev/null +++ b/vlib/v/checker/tests/overflow_int_err.vv @@ -0,0 +1,10 @@ +fn main() { + a := -2147483648 + b := 2147483647 + c := -2147483649 + d := 2147483648 + println(a) + println(b) + println(c) + println(d) +}