mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: more precise error handling of large binary literals like 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000 (#16775)
This commit is contained in:
parent
508bfbf892
commit
a8f6f9ed60
|
@ -333,3 +333,20 @@ fn test_parse() {
|
||||||
assert u64(1) == '1'.parse_uint(10, 8) or { 0 }
|
assert u64(1) == '1'.parse_uint(10, 8) or { 0 }
|
||||||
assert u64(1) == '1'.parse_uint(16, 8) or { 0 }
|
assert u64(1) == '1'.parse_uint(16, 8) or { 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_interpolate_binary_literals() {
|
||||||
|
assert ' 1 ${i64(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000)}' == ' 1 -9223372036854775808'
|
||||||
|
assert ' 2 ${i64(0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)}' == ' 2 -1'
|
||||||
|
assert ' 3 ${i64(0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)}' == ' 3 9223372036854775807'
|
||||||
|
assert ' 4 ${u64(0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000)}' == ' 4 9223372036854775808'
|
||||||
|
assert ' 5 ${u64(0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)}' == ' 5 18446744073709551615'
|
||||||
|
assert ' 6 ${u64(0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)}' == ' 6 9223372036854775807'
|
||||||
|
assert ' 7 ${u32(0b111_1111_1111_1111_1111)}' == ' 7 524287'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interpolate_literal_limits() {
|
||||||
|
assert ' 8 ${u32(2147483648)}' == ' 8 2147483648'
|
||||||
|
assert ' 9 ${u64(0xFF_FF_FF_FF_FF_FF_FF_FF)}' == ' 9 18446744073709551615'
|
||||||
|
assert '10 ${u32(0o377777_77777)}' == '10 4294967295'
|
||||||
|
assert '11 ${i64(-2147483647)}' == '11 -2147483647'
|
||||||
|
}
|
||||||
|
|
|
@ -165,27 +165,56 @@ fn (mut c Checker) string_lit(mut node ast.StringLiteral) ast.Type {
|
||||||
return ast.string_type
|
return ast.string_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LoHiLimit {
|
||||||
|
lower string
|
||||||
|
higher string
|
||||||
|
}
|
||||||
|
|
||||||
|
const iencoding_map = {
|
||||||
|
`B`: LoHiLimit{'1000000000000000000000000000000000000000000000000000000000000000', '1111111111111111111111111111111111111111111111111111111111111111'}
|
||||||
|
`O`: LoHiLimit{'1000000000000000000000', '1777777777777777777777'}
|
||||||
|
`_`: LoHiLimit{'9223372036854775808', '18446744073709551615'}
|
||||||
|
`X`: LoHiLimit{'8000000000000000', 'FFFFFFFFFFFFFFFF'}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) int_lit(mut node ast.IntegerLiteral) ast.Type {
|
fn (mut c Checker) int_lit(mut node ast.IntegerLiteral) ast.Type {
|
||||||
if node.val.len < 17 {
|
if node.val.len < 17 {
|
||||||
// can not be a too large number, no need for more expensive checks
|
// can not be a too large number, no need for more expensive checks
|
||||||
return ast.int_literal_type
|
return ast.int_literal_type
|
||||||
}
|
}
|
||||||
lit := node.val.replace('_', '').all_after('-')
|
lit := node.val.replace('_', '').all_after('-').to_upper()
|
||||||
is_neg := node.val.starts_with('-')
|
is_neg := node.val.starts_with('-')
|
||||||
limit := if is_neg { '9223372036854775808' } else { '18446744073709551615' }
|
if lit.len > 2 && lit[0] == `0` && lit[1] in [`B`, `X`, `O`] {
|
||||||
message := 'integer literal ${node.val} overflows int'
|
if lohi := checker.iencoding_map[lit[1]] {
|
||||||
|
c.check_num_literal(lohi, is_neg, lit[2..]) or { c.num_lit_overflow_error(node) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lohi := checker.iencoding_map[`_`]
|
||||||
|
c.check_num_literal(lohi, is_neg, lit) or { c.num_lit_overflow_error(node) }
|
||||||
|
}
|
||||||
|
return ast.int_literal_type
|
||||||
|
}
|
||||||
|
|
||||||
|
[direct_array_access]
|
||||||
|
fn (mut c Checker) check_num_literal(lohi LoHiLimit, is_neg bool, lit string) ! {
|
||||||
|
limit := if is_neg { lohi.lower } else { lohi.higher }
|
||||||
|
if lit.len < limit.len {
|
||||||
|
return
|
||||||
|
}
|
||||||
if lit.len > limit.len {
|
if lit.len > limit.len {
|
||||||
c.error(message, node.pos)
|
return error('length overflow')
|
||||||
} else if lit.len == limit.len {
|
}
|
||||||
|
if lit.len == limit.len {
|
||||||
for i, digit in lit {
|
for i, digit in lit {
|
||||||
if digit > limit[i] {
|
if digit > limit[i] {
|
||||||
c.error(message, node.pos)
|
return error('value overflow at i: ${i}')
|
||||||
} else if digit < limit[i] {
|
} else if digit < limit[i] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ast.int_literal_type
|
|
||||||
|
fn (mut c Checker) num_lit_overflow_error(node &ast.IntegerLiteral) {
|
||||||
|
c.error('integer literal ${node.val} overflows int', node.pos)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user