summaryrefslogtreecommitdiff
path: root/miscutils/bc.c
diff options
context:
space:
mode:
authorDenys Vlasenko2018-12-22 21:37:46 +0100
committerDenys Vlasenko2018-12-22 21:37:46 +0100
commit1557b76edde8bc810f82ac67e3b83b2d6ccce51c (patch)
tree68cb23b301a45439f993f98c2105861dfc385673 /miscutils/bc.c
parentec74a9c14572f17ad4a5ff94813a743bc6e6222d (diff)
downloadbusybox-1557b76edde8bc810f82ac67e3b83b2d6ccce51c.zip
busybox-1557b76edde8bc810f82ac67e3b83b2d6ccce51c.tar.gz
bc: shrink zbc_num_ulong()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/bc.c')
-rw-r--r--miscutils/bc.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 7be2d0b..876244b 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;