From aa5b609d9555400128b531d2c7ef8de0af7d4924 Mon Sep 17 00:00:00 2001 From: shadowninja55 <49539636+shadowninja55@users.noreply.github.com> Date: Fri, 9 Jul 2021 07:02:10 -0400 Subject: [PATCH] checker: check integer literals (#10706) --- vlib/v/checker/check_types.v | 25 ++++++++++++++++++++++ vlib/v/checker/checker.v | 2 +- vlib/v/checker/tests/oversized_int_lit.out | 8 +++++++ vlib/v/checker/tests/oversized_int_lit.vv | 2 ++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/oversized_int_lit.out create mode 100644 vlib/v/checker/tests/oversized_int_lit.vv diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 6b0e34a176..c4bac909c6 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -487,6 +487,31 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Typ return ast.string_type } +pub fn (mut c Checker) int_lit(mut node ast.IntegerLiteral) ast.Type { + if node.val.len < 17 { + // can not be a too large number, no need for more expensive checks + return ast.int_literal_type + } + lit := node.val.replace('_', '').all_after('-') + is_neg := node.val.starts_with('-') + limit := if is_neg { '9223372036854775808' } else { '18446744073709551615' } + message := 'integer literal $node.val overflows int' + + if lit.len > limit.len { + c.error(message, node.pos) + } else if lit.len == limit.len { + for i, digit in lit { + if digit > limit[i] { + c.error(message, node.pos) + } else if digit < limit[i] { + break + } + } + } + + return ast.int_literal_type +} + pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallExpr) { mut inferred_types := []ast.Type{} for gi, gt_name in f.generic_names { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 17519d80e6..edae74653b 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -5004,7 +5004,7 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type { return c.infix_expr(mut node) } ast.IntegerLiteral { - return ast.int_literal_type + return c.int_lit(mut node) } ast.LockExpr { return c.lock_expr(mut node) diff --git a/vlib/v/checker/tests/oversized_int_lit.out b/vlib/v/checker/tests/oversized_int_lit.out new file mode 100644 index 0000000000..30a9622631 --- /dev/null +++ b/vlib/v/checker/tests/oversized_int_lit.out @@ -0,0 +1,8 @@ +vlib/v/checker/tests/oversized_int_lit.vv:1:8: error: integer literal 18446744073709551616 overflows int + 1 | assert 18446744073709551616 > 0 + | ~~~~~~~~~~~~~~~~~~~~ + 2 | assert -9223372036854775809 < 0 +vlib/v/checker/tests/oversized_int_lit.vv:2:8: error: integer literal -9223372036854775809 overflows int + 1 | assert 18446744073709551616 > 0 + 2 | assert -9223372036854775809 < 0 + | ~~~~~~~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/oversized_int_lit.vv b/vlib/v/checker/tests/oversized_int_lit.vv new file mode 100644 index 0000000000..d6e3a27628 --- /dev/null +++ b/vlib/v/checker/tests/oversized_int_lit.vv @@ -0,0 +1,2 @@ +assert 18446744073709551616 > 0 +assert -9223372036854775809 < 0