]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib: [strutils] avoid integer overflow on large values
authorDave Reisner <d@falconindy.com>
Tue, 15 Feb 2011 09:06:08 +0000 (10:06 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 18 Apr 2011 12:25:23 +0000 (14:25 +0200)
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 <d@falconindy.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
lib/strutils.c
tests/expected/misc/strtosize

index 94635b1e8951b34d67def26f92add1810356c17e..b63eea4690e76d43b278f339be85acbd2686144a 100644 (file)
@@ -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 <number>[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 */
index d1c039d2df2e38b67c450d584ed4e9b6c506878b..0dd5e3e761f756a541da1d8077fb65ffd80c6437 100644 (file)
@@ -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