From f9e05dafd0fa36b2cb29eb30250dc63039a34bf2 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Tue, 15 Feb 2011 10:06:08 +0100 Subject: [PATCH] lib: [strutils] avoid integer overflow on large values This is visible on a 2TB disk via lsblk, where a large partition incorrectly displays as 1.171798692T instead of 1.8T. This is corrected by using a uint64_t type instead of a simple int -- consistant with the type used in lsblk.c to represent the raw size in bytes. [kzak@redhat.com: - add EiB support - add size_to_human_string() to regression tests] Signed-off-by: Dave Reisner Signed-off-by: Karel Zak --- lib/strutils.c | 18 +++++++++--- tests/expected/misc/strtosize | 52 +++++++++++++++++------------------ 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/lib/strutils.c b/lib/strutils.c index 8089fbe8b3..39c9bdf022 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -245,8 +245,9 @@ static int get_exp(uint64_t n) char *size_to_human_string(uint64_t bytes) { char buf[32]; - int dec, frac, exp; - const char *letters = "BKMGTP"; + int dec, exp; + uint64_t frac; + const char *letters = "BKMGTPE"; char c; exp = get_exp(bytes); @@ -254,6 +255,10 @@ char *size_to_human_string(uint64_t bytes) dec = exp ? bytes / (1ULL << exp) : bytes; frac = exp ? bytes % (1ULL << exp) : 0; + /* fprintf(stderr, "exp: %d, c: %c, dec: %d, frac: %jd\n", + * exp, c, dec, frac); + */ + if (frac) { /* round */ frac = (frac / (1ULL << (exp - 10)) + 50) / 100; @@ -267,7 +272,7 @@ char *size_to_human_string(uint64_t bytes) if (!dp || !*dp) dp = "."; - snprintf(buf, sizeof(buf), "%d%s%d%c", dec, dp, frac, c); + snprintf(buf, sizeof(buf), "%d%s%jd%c", dec, dp, frac, c); } else snprintf(buf, sizeof(buf), "%d%c", dec, c); @@ -280,6 +285,7 @@ char *size_to_human_string(uint64_t bytes) int main(int argc, char *argv[]) { uintmax_t size = 0; + char *hum; if (argc < 2) { fprintf(stderr, "usage: %s [suffix]\n", argv[0]); @@ -289,7 +295,11 @@ int main(int argc, char *argv[]) if (strtosize(argv[1], &size)) errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]); - printf("%25s : %20ju\n", argv[1], size); + hum = size_to_human_string(size); + + printf("%25s : %20ju : %8s\n", argv[1], size, hum); + free(hum); + return EXIT_FAILURE; } #endif /* TEST_PROGRAM */ diff --git a/tests/expected/misc/strtosize b/tests/expected/misc/strtosize index d1c039d2df..0dd5e3e761 100644 --- a/tests/expected/misc/strtosize +++ b/tests/expected/misc/strtosize @@ -1,30 +1,30 @@ test_strutils: invalid size '-1' value - 0 : 0 - 1 : 1 - 123 : 123 - 18446744073709551615 : 18446744073709551615 - 1K : 1024 - 1KiB : 1024 - 1M : 1048576 - 1MiB : 1048576 - 1G : 1073741824 - 1GiB : 1073741824 - 1T : 1099511627776 - 1TiB : 1099511627776 - 1P : 1125899906842624 - 1PiB : 1125899906842624 - 1E : 1152921504606846976 - 1EiB : 1152921504606846976 - 1KB : 1000 - 1MB : 1000000 - 1GB : 1000000000 - 1TB : 1000000000000 - 1PB : 1000000000000000 - 1EB : 1000000000000000000 + 0 : 0 : 0B + 1 : 1 : 1B + 123 : 123 : 123B + 18446744073709551615 : 18446744073709551615 : 16E + 1K : 1024 : 1K + 1KiB : 1024 : 1K + 1M : 1048576 : 1M + 1MiB : 1048576 : 1M + 1G : 1073741824 : 1G + 1GiB : 1073741824 : 1G + 1T : 1099511627776 : 1T + 1TiB : 1099511627776 : 1T + 1P : 1125899906842624 : 1P + 1PiB : 1125899906842624 : 1P + 1E : 1152921504606846976 : 1E + 1EiB : 1152921504606846976 : 1E + 1KB : 1000 : 1000B + 1MB : 1000000 : 976.6K + 1GB : 1000000000 : 953.7M + 1TB : 1000000000000 : 931.3G + 1PB : 1000000000000000 : 909.5T + 1EB : 1000000000000000000 : 888.2P test_strutils: invalid size '' value test_strutils: invalid size ' ' value - 1 : 1 + 1 : 1 : 1B test_strutils: invalid size '1 ' value - 0x0a : 10 - 0xff00 : 65280 - 0x80000000 : 2147483648 + 0x0a : 10 : 10B + 0xff00 : 65280 : 63.8K + 0x80000000 : 2147483648 : 2G -- 2.47.3