Reject negative unsigned string values

This commit is contained in:
udo 2026-07-18 16:22:14 +00:00
parent 22efea8ecd
commit 39d4b41e2b
3 changed files with 15 additions and 4 deletions

View File

@ -14,7 +14,8 @@ to_bool
int_val
:content
Parses a trimmed string as a base-10 unsigned integer.
Parses a trimmed string as a base-10 unsigned integer. An optional leading `+`
is accepted. Negative and overflowing values return the fallback.
Unlike `int_val()`, the whole trimmed string must be consumed by the parser. Empty strings and partially parsed values such as `"42px"` return the fallback.

View File

@ -149,6 +149,7 @@ RENDER(Request& context)
cfg["yes"] = "yes";
cfg["no"] = "off";
check("to_u64() / to_s64() / to_f64() / to_bool()", to_u64(cfg["u64"], 7) == 42 && to_u64(cfg["bad"], 7) == 7 && to_s64(cfg["s64"], 5) == -12 && to_s64(cfg["bad"], 5) == 5 && to_f64(cfg["f64"], 1.0) > 3.49 && to_f64(cfg["bad"], 1.25) == 1.25 && to_bool(cfg["yes"], false) && !to_bool(cfg["no"], true) && !to_bool("unknown", false), var_dump(cfg));
check("to_u64() rejects negative and overflowing text", to_u64("-1", 7) == 7 && to_u64("+42", 7) == 42 && to_u64("18446744073709551615", 7) == 18446744073709551615ULL && to_u64("18446744073709551616", 7) == 7, std::to_string(to_u64("-1", 7)) + "/" + std::to_string(to_u64("18446744073709551616", 7)));
DValue perf = request_perf();
u64 module_misses = perf["unit_module_cache_miss_count"].to_u64();

View File

@ -929,9 +929,18 @@ u64 to_u64(String s, u64 fallback)
String raw = trim(s);
if(raw == "")
return(fallback);
char* end = 0;
unsigned long long value = strtoull(raw.c_str(), &end, 10);
return(end && *end == 0 ? (u64)value : fallback);
u64 value = 0;
u64 offset = raw[0] == '+' ? 1 : 0;
if(offset == raw.size())
return(fallback);
for(; offset < raw.size(); offset++)
{
char c = raw[offset];
if(c < '0' || c > '9' || value > (UINT64_MAX - (u64)(c - '0')) / 10)
return(fallback);
value = value * 10 + (u64)(c - '0');
}
return(value);
}
s64 to_s64(String s, s64 fallback)