wcc: reject final-band integer overflow; restore rewind columns

This commit is contained in:
2026-08-09 03:25:17 +09:00
parent cd11d6e573
commit 53a9e94736
5 changed files with 76 additions and 9 deletions

View File

@@ -269,6 +269,9 @@ fn skipws(l: *lex) bool = {
fn parseint(p: *u8, n: u64, base: i32, ok: *bool) u64 = {
let v: u64 = 0u64;
let b: u64 = base: u64;
let cutoff: u64 = ~0u64 / b;
let cutlim: u64 = ~0u64 % b;
let got: bool = false;
let i: u64 = 0u64;
for (i < n) {
@@ -294,8 +297,11 @@ fn parseint(p: *u8, n: u64, base: i32, ok: *bool) u64 = {
};
if (d < 0) { *ok = false; return 0u64; };
if (d >= base) { *ok = false; return 0u64; };
if (v > ~0u64 / (base: u64)) { *ok = false; return 0u64; };
v = v * (base: u64) + (d: u64);
if (v > cutoff || (v == cutoff && (d: u64) > cutlim)) {
*ok = false;
return 0u64;
};
v = v * b + (d: u64);
got = true;
i += 1u64;
};
@@ -551,6 +557,7 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
if (pc >= 0) {
if (isidstart(pc: rune)) {
let sb: u64 = l.lpos;
let sc: i32 = l.col;
for (true) {
let cc: i32 = lpeek(l, 0u64);
if (cc < 0) { break; };
@@ -591,6 +598,7 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
out.tsuffix = strings.dup(view);
} else {
l.lpos = sb;
l.col = sc;
};
};
};

View File

@@ -309,3 +309,32 @@ fn checkfloat(src: str, want: u64) void = {
checkfloat("1.0e308", 0x7FE1CCF385EBC8A0u64);
checkfloat("2.225073858507202e-308", 0x0010000000000001u64);
};
@test fn intfinalband() void = {
let src: str = "18446744073709551616";
let l: lex;
lexinit(&l, "t", src.ptr, src.len: u64);
let t: tok;
lexnext(&l, &t);
assert(!(t.kind != tkind.TK_ERR));
assert(!(l.errs != 1));
};
@test fn suffixrewindcols() void = {
let src: str = "1foo bar";
let l: lex;
lexinit(&l, "t", src.ptr, src.len: u64);
let t: tok;
lexnext(&l, &t);
assert(!(t.kind != tkind.TK_INT));
assert(!(t.col != 1));
assert(!(t.uval != 1u64));
lexnext(&l, &t);
assert(!(t.kind != tkind.TK_IDENT));
assert(!(t.col != 2));
assert(!(t.text != "foo"));
lexnext(&l, &t);
assert(!(t.kind != tkind.TK_IDENT));
assert(!(t.col != 6));
assert(!(t.text != "bar"));
};