From owner-svn-src-all@FreeBSD.ORG Wed Mar 23 22:08:01 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BF2C6106564A; Wed, 23 Mar 2011 22:08:01 +0000 (UTC) (envelope-from delphij@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B023A8FC13; Wed, 23 Mar 2011 22:08:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2NM81Su008807; Wed, 23 Mar 2011 22:08:01 GMT (envelope-from delphij@svn.freebsd.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2NM818d008805; Wed, 23 Mar 2011 22:08:01 GMT (envelope-from delphij@svn.freebsd.org) Message-Id: <201103232208.p2NM818d008805@svn.freebsd.org> From: Xin LI Date: Wed, 23 Mar 2011 22:08:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219939 - head/lib/libutil X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Mar 2011 22:08:01 -0000 Author: delphij Date: Wed Mar 23 22:08:01 2011 New Revision: 219939 URL: http://svn.freebsd.org/changeset/base/219939 Log: humanize_number(3) multiply the input number by 100, which could cause an integer overflow when the input is very large (for example, 100 Pi would become about 10 Ei which exceeded signed int64_t). Solve this issue by splitting the division into two parts and avoid the multiplication. PR: bin/146205 Reviewed by: arundel MFC after: 1 month Modified: head/lib/libutil/humanize_number.c Modified: head/lib/libutil/humanize_number.c ============================================================================== --- head/lib/libutil/humanize_number.c Wed Mar 23 22:06:09 2011 (r219938) +++ head/lib/libutil/humanize_number.c Wed Mar 23 22:08:01 2011 (r219939) @@ -43,11 +43,11 @@ __FBSDID("$FreeBSD$"); #include int -humanize_number(char *buf, size_t len, int64_t bytes, +humanize_number(char *buf, size_t len, int64_t quotient, const char *suffix, int scale, int flags) { const char *prefixes, *sep; - int b, i, r, maxscale, s1, s2, sign; + int i, r, remainder, maxscale, s1, s2, sign; int64_t divisor, max; size_t baselen; @@ -55,6 +55,8 @@ humanize_number(char *buf, size_t len, i assert(suffix != NULL); assert(scale >= 0); + remainder = 0; + if (flags & HN_DIVISOR_1000) { /* SI for decimal multiplies */ divisor = 1000; @@ -86,13 +88,12 @@ humanize_number(char *buf, size_t len, i if (len > 0) buf[0] = '\0'; - if (bytes < 0) { + if (quotient < 0) { sign = -1; - bytes *= -100; + quotient = -quotient; baselen = 3; /* sign, digit, prefix */ } else { sign = 1; - bytes *= 100; baselen = 2; /* digit, prefix */ } if (flags & HN_NOSPACE) @@ -109,7 +110,7 @@ humanize_number(char *buf, size_t len, i if (scale & (HN_AUTOSCALE | HN_GETSCALE)) { /* See if there is additional columns can be used. */ - for (max = 100, i = len - baselen; i-- > 0;) + for (max = 1, i = len - baselen; i-- > 0;) max *= 10; /* @@ -117,30 +118,37 @@ humanize_number(char *buf, size_t len, i * If there will be an overflow by the rounding below, * divide once more. */ - for (i = 0; bytes >= max - 50 && i < maxscale; i++) - bytes /= divisor; + for (i = 0; + (quotient >= max || (quotient == max - 1 && remainder >= 950)) && + i < maxscale; i++) { + remainder = quotient % divisor; + quotient /= divisor; + } if (scale & HN_GETSCALE) return (i); - } else - for (i = 0; i < scale && i < maxscale; i++) - bytes /= divisor; + } else { + for (i = 0; i < scale && i < maxscale; i++) { + remainder = quotient % divisor; + quotient /= divisor; + } + } /* If a value <= 9.9 after rounding and ... */ - if (bytes < 995 && i > 0 && flags & HN_DECIMAL) { + if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) { /* baselen + \0 + .N */ if (len < baselen + 1 + 2) return (-1); - b = ((int)bytes + 5) / 10; - s1 = b / 10; - s2 = b % 10; + s1 = (int)quotient + ((remainder + 50) / 1000); + s2 = ((remainder + 50) / 100) % 10; r = snprintf(buf, len, "%d%s%d%s%s%s", sign * s1, localeconv()->decimal_point, s2, sep, SCALE2PREFIX(i), suffix); } else r = snprintf(buf, len, "%" PRId64 "%s%s%s", - sign * ((bytes + 50) / 100), + sign * (quotient + (remainder + 50) / 1000), sep, SCALE2PREFIX(i), suffix); return (r); } +