hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 37bec9536e154779f844ec17e6f069bdbd857b22
parent 39b03bce994aac936c2ce7eb7b7665e6f5f38d9b
Author: Bor Grošelj Simić <bgs@turminal.net>
Date:   Tue,  7 Feb 2023 23:13:16 +0100

hare::lex: error out on overflowing integer exponents

References: https://todo.sr.ht/~sircmpwn/hare/737
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>

Diffstat:
Mhare/lex/lex.ha | 38+++++++++++++++++++++++---------------
Mhare/parse/+test/loc.ha | 2+-
2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha @@ -14,6 +14,7 @@ use sort; use strconv; use strings; use strio; +use types; export type lexer = struct { in: io::handle, @@ -563,21 +564,21 @@ fn lex_literal(lex: *lexer) (token | error) = { case void => yield ""; }; - let suff = if (suff == "u8") ltok::LIT_U8 - else if (suff == "u16") ltok::LIT_U16 - else if (suff == "u32") ltok::LIT_U32 - else if (suff == "u64") ltok::LIT_U64 - else if (suff == "u") ltok::LIT_UINT - else if (suff == "z") ltok::LIT_SIZE - else if (suff == "i8") ltok::LIT_I8 - else if (suff == "i16") ltok::LIT_I16 - else if (suff == "i32") ltok::LIT_I32 - else if (suff == "i64") ltok::LIT_I64 - else if (suff == "i") ltok::LIT_INT - else if (suff == "" && !float && exp >= 0) ltok::LIT_ICONST - else if (suff == "f32") ltok::LIT_F32 - else if (suff == "f64") ltok::LIT_F64 - else if (suff == "" && (float || exp < 0)) ltok::LIT_FCONST + let (suff, signed) = if (suff == "u8") (ltok::LIT_U8, false) + else if (suff == "u16") (ltok::LIT_U16, false) + else if (suff == "u32") (ltok::LIT_U32, false) + else if (suff == "u64") (ltok::LIT_U64, false) + else if (suff == "u") (ltok::LIT_UINT, false) + else if (suff == "z") (ltok::LIT_SIZE, false) + else if (suff == "i8") (ltok::LIT_I8, true) + else if (suff == "i16") (ltok::LIT_I16, true) + else if (suff == "i32") (ltok::LIT_I32, true) + else if (suff == "i64") (ltok::LIT_I64, true) + else if (suff == "i") (ltok::LIT_INT, true) + else if (suff == "" && !float && exp >= 0) (ltok::LIT_ICONST, false) + else if (suff == "f32") (ltok::LIT_F32, false) + else if (suff == "f64") (ltok::LIT_F64, false) + else if (suff == "" && (float || exp < 0)) (ltok::LIT_FCONST, false) else return syntaxerr(loc, "invalid literal suffix"); let exp = if (exp < 0) switch (suff) { @@ -598,7 +599,14 @@ fn lex_literal(lex: *lexer) (token | error) = { let val = match (val) { case let val: u64 => for (let i = 0z; i < exp; i += 1) { + let old = val; val *= 10; + if (val / 10 != old) { + return syntaxerr(loc, "overflow in exponent"); + }; + }; + if (signed && val > types::I64_MIN: u64) { + return syntaxerr(loc, "overflow in exponent"); }; yield val; case let val: f64 => diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha @@ -52,7 +52,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) { expr_testloc("(foo, bar)"); expr_testloc("null", "void", "true", `"שלום"`, "'a'"); expr_testloc("[foo, bar]"); - expr_testloc("123", "-123.456", "123z", "123e+456"); + expr_testloc("123", "-123.456", "123z", "123e+3"); expr_testloc("continue", "continue :foo"); expr_testloc("defer foo"); expr_testloc("delete(foo[bar])", "delete(foo[bar..baz])");