From 1557b76edde8bc810f82ac67e3b83b2d6ccce51c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 21:37:46 +0100 Subject: [PATCH] bc: shrink zbc_num_ulong() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7be2d0b9b..876244b34 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1442,20 +1442,21 @@ static void bc_num_copy(BcNum *d, BcNum *s) static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) { size_t i; - unsigned long pow, result; + unsigned long result; if (n->neg) RETURN_STATUS(bc_error("negative number")); - for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { - unsigned long prev = result, powprev = pow; - - result += ((unsigned long) n->num[i]) * pow; - pow *= 10; - - if (result < prev || pow < powprev) + result = 0; + i = n->len; + while (i > n->rdx) { + unsigned long prev = result; + result = result * 10 + n->num[--i]; + // Even overflowed N*10 can still satisfy N*10>=N. For example, + // 0x1ff00000 * 10 is 0x13f600000, + // or 0x3f600000 truncated to 32 bits. Which is larger. + // However, (N*10)/8 < N check is always correct. + if ((result / 8) < prev) RETURN_STATUS(bc_error("overflow")); - prev = result; - powprev = pow; } *result_p = result; -- 2.25.1