[git commit] bc: shrink zbc_num_ulong()

Denys Vlasenko vda.linux at googlemail.com
Sat Dec 22 20:37:46 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=1557b76edde8bc810f82ac67e3b83b2d6ccce51c
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 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;
 


More information about the busybox-cvs mailing list