Fix string to uint64_t conversion.
authorLasse Collin <lasse.collin@tukaani.org>
Fri, 11 Jun 2010 18:43:28 +0000 (21:43 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Fri, 11 Jun 2010 18:43:28 +0000 (21:43 +0300)
Thanks to Denis Excoffier for the bug report.

src/xz/util.c
src/xzdec/xzdec.c

index deb5dcc..19f5eee 100644 (file)
@@ -56,11 +56,17 @@ str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
 
        do {
                // Don't overflow.
-               if (result > (UINT64_MAX - 9) / 10)
+               if (result > UINT64_MAX / 10)
                        goto error;
 
                result *= 10;
-               result += *value - '0';
+
+               // Another overflow check
+               const uint32_t add = *value - '0';
+               if (UINT64_MAX - add < result)
+                       goto error;
+
+               result += add;
                ++value;
        } while (*value >= '0' && *value <= '9');
 
index 8518d36..7f2e0fd 100644 (file)
@@ -153,6 +153,9 @@ memlimit_init(void)
 /// \brief      Convert a string to uint64_t
 ///
 /// This is rudely copied from src/xz/util.c and modified a little. :-(
+/// Since this function is used only for parsing the memory usage limit,
+/// this cheats a little and saturates too big values to UINT64_MAX instead
+/// of giving an error.
 ///
 /// \param      max     Return value when the string "max" was specified.
 ///
@@ -173,11 +176,17 @@ str_to_uint64(const char *value, uint64_t max)
 
        do {
                // Don't overflow.
-               if (result > (UINT64_MAX - 9) / 10)
+               if (result > UINT64_MAX / 10)
                        return UINT64_MAX;
 
                result *= 10;
-               result += *value - '0';
+
+               // Another overflow check
+               const uint32_t add = *value - '0';
+               if (UINT64_MAX - add < result)
+                       return UINT64_MAX;
+
+               result += add;
                ++value;
        } while (*value >= '0' && *value <= '9');