From ea2feccbf8b4fb22a3bd0a2dd3b477c26dc6373d Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Sat, 12 Jul 2025 11:38:38 -0400 Subject: [PATCH] common: set errno=0 before calling strto{l,ul,ull} The strto{l,ul,ull} functions do not set errno upon a successful return, so a successful return from a maximally valued input could be misinterpreted as an overflow error if errno happened already to be set to ERANGE before the call. To guard against this edge case, always set errno to zero before calling these functions if checking errno afterward. Changelog-None --- common/bolt11.c | 1 + common/json_parse.c | 2 ++ common/json_parse_simple.c | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/bolt11.c b/common/bolt11.c index bcc00cf38..bb3db5b04 100644 --- a/common/bolt11.c +++ b/common/bolt11.c @@ -833,6 +833,7 @@ struct bolt11 *bolt11_decode_nosig(const tal_t *ctx, const char *str, * anything except a `multiplier` (see table above)... MUST fail the * payment. **/ + errno = 0; amount = strtoull(amountstr, &end, 10); if (amount == ULLONG_MAX && errno == ERANGE) return decode_fail(b11, fail, diff --git a/common/json_parse.c b/common/json_parse.c index 1fb1fa97b..7b5c31c81 100644 --- a/common/json_parse.c +++ b/common/json_parse.c @@ -233,6 +233,7 @@ static void parse_number(const char **guide, u32 *number) char *endp; long int l; + errno = 0; l = strtol(*guide, &endp, 10); assert(endp != *guide); assert(errno != ERANGE); @@ -518,6 +519,7 @@ bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok, char *end; unsigned long btc, sat; + errno = 0; btc = strtoul(buffer + tok->start, &end, 10); if (btc == ULONG_MAX && errno == ERANGE) return false; diff --git a/common/json_parse_simple.c b/common/json_parse_simple.c index a40cb02fb..0842fc58b 100644 --- a/common/json_parse_simple.c +++ b/common/json_parse_simple.c @@ -66,6 +66,7 @@ bool json_to_u64(const char *buffer, const jsmntok_t *tok, u64 *num) char *end; unsigned long long l; + errno = 0; l = strtoull(buffer + tok->start, &end, 0); if (end != buffer + tok->end) return false; @@ -88,6 +89,7 @@ bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num) char *end; long long l; + errno = 0; l = strtoll(buffer + tok->start, &end, 0); if (end != buffer + tok->end) return false; @@ -129,7 +131,7 @@ bool json_to_double(const char *buffer, const jsmntok_t *tok, double *num) if (end != buffer + tok->end) return false; - /* Check for overflow */ + /* Check for overflow/underflow */ if (errno == ERANGE) return false;