strconv: reject overflow before arithmetic
This commit is contained in:
@@ -129,6 +129,9 @@ fn ck_uint_ovf(id: i32, s: str, b: base) void = {
|
||||
|
||||
cki_ovf(7, "9223372036854775808", base.DEC);
|
||||
cki_ovf(8, "-9223372036854775809", base.DEC);
|
||||
// The last multiply wraps to a value larger than its prefix, so a
|
||||
// post-arithmetic `n < old` check misses this overflow.
|
||||
cki_ovf(19, "21000000000000000000", base.DEC);
|
||||
|
||||
cki(9, "0", base.DEC, 0);
|
||||
cki(10, "1", base.DEC, 1);
|
||||
@@ -168,6 +171,7 @@ fn ck_uint_ovf(id: i32, s: str, b: base) void = {
|
||||
cku_ovf(35, "18446744073709551616", base.DEC);
|
||||
cku_ovf(36, "184467440737095516150", base.DEC);
|
||||
cku_ovf(37, "-1", base.DEC);
|
||||
cku_ovf(46, "21000000000000000000", base.DEC);
|
||||
|
||||
cku(38, "0", base.DEC, 0u64);
|
||||
cku(39, "1", base.DEC, 1u64);
|
||||
@@ -207,6 +211,87 @@ fn ck_uint_ovf(id: i32, s: str, b: base) void = {
|
||||
ck_uint(62, "110101", base.BIN, 53u64: uint); // 0b110101
|
||||
};
|
||||
|
||||
@test fn test_narrow_parse_boundaries() void = {
|
||||
match (stoi16("32767", base.DEC)) {
|
||||
case let v: i16 => assert(v == 32767i16);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stoi16("-32768", base.DEC)) {
|
||||
case let v: i16 => assert(v == -32768i16);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stoi16("32768", base.DEC)) {
|
||||
case let v: i16 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
match (stoi16("-32769", base.DEC)) {
|
||||
case let v: i16 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
|
||||
match (stoi8("127", base.DEC)) {
|
||||
case let v: i8 => assert(v == 127i8);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stoi8("-128", base.DEC)) {
|
||||
case let v: i8 => assert(v == -128i8);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stoi8("128", base.DEC)) {
|
||||
case let v: i8 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
match (stoi8("-129", base.DEC)) {
|
||||
case let v: i8 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
|
||||
match (stou16("65535", base.DEC)) {
|
||||
case let v: u16 => assert(v == 65535u16);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stou16("65536", base.DEC)) {
|
||||
case let v: u16 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
match (stou8("255", base.DEC)) {
|
||||
case let v: u8 => assert(v == 255u8);
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => abort();
|
||||
};
|
||||
match (stou8("256", base.DEC)) {
|
||||
case let v: u8 => abort();
|
||||
case let e: invalid => abort();
|
||||
case let e: overflow => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn test_strerror_static() void = {
|
||||
let inv: invalid = 0: invalid;
|
||||
let ie: error = inv;
|
||||
let ia: str = strerror(ie);
|
||||
let ib: str = strerror(ie);
|
||||
assert(ia.ptr == ib.ptr);
|
||||
assert(streq(ia, "input is not a valid number"));
|
||||
|
||||
let ov: overflow;
|
||||
let oe: error = ov;
|
||||
let oa: str = strerror(oe);
|
||||
let ob: str = strerror(oe);
|
||||
assert(oa.ptr == ob.ptr);
|
||||
assert(streq(oa, "input number doesn't fit target type"));
|
||||
};
|
||||
|
||||
// Verbatim ports of ref/hare/strconv/utos.ha:74-103 (utos/utos_bases) and
|
||||
// itos.ha:54-87 (itos/itos_bases) — Hare's format tests are flat assert
|
||||
// sequences too. Radix-literal inputs are written in DECIMAL (ww value
|
||||
|
||||
Reference in New Issue
Block a user