strconv: reject overflow before arithmetic

This commit is contained in:
2026-08-09 17:50:47 +09:00
parent 8e2e6ae162
commit 976dc8a813
6 changed files with 118 additions and 19 deletions

View File

@@ -8,7 +8,6 @@ package strconv;
import ascii;
import bytes;
import os;
import strings;
// invalid — input wasn't a valid number in the requested format.
@@ -224,14 +223,12 @@ fn parseint(s: str, b: base) ((bool, u64) | invalid | overflow) = {
return i: invalid;
};
let old: u64 = n;
n = n * nb;
n = n + digit;
if (n < old) {
// Check before multiplying: a wrapped value is not necessarily
// smaller than the preceding prefix.
if (n > (18446744073709551615u64 - digit) / nb) {
return overflow{};
};
n = n * nb + digit;
i += 1;
};
@@ -403,13 +400,12 @@ export fn stoz(s: str, b: base) (size | invalid | overflow) = {
// both"); ftos.ww's f64tos is the live one. f32tos follows in fold-5b
// (task #67, gated on the #143 f32-arg-push cgen fix).
// strerror — convert an strconv error to a user-readable string.
// Returns owned str; release via os.free. Mirrors Hare's
// strconv::strerror.
// strerror — convert a strconv error to a user-readable string.
// The returned string has static storage and must not be freed.
export fn strerror(e: error) str = {
match (e) {
case let v: invalid => return strings.dup("input is not a valid number");
case let v: overflow => return strings.dup("input number doesn't fit target type");
case let v: invalid => return "input is not a valid number";
case let v: overflow => return "input number doesn't fit target type";
};
return strings.dup("");
return "";
};