]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add tighter checks to avoid reading past end of buffer
authorBrian Weaver <cmdrclueless@gmail.com>
Tue, 25 Sep 2012 13:51:12 +0000 (09:51 -0400)
committerBrian Weaver <cmdrclueless@gmail.com>
Wed, 26 Sep 2012 05:39:51 +0000 (01:39 -0400)
The string to base 8/10 conversion routines could read past the
counted end of the buffer if the string is correctly formated.
The number of characters is now checked and decremented for every
character that is consumed for processing.

successfully passes 'make check-TESTS'

libarchive/archive_read_support_format_tar.c

index 4538331f3d05382a8e129c0e326fe9684a40bf8a..ed5799333dde4dc21d41e5b83f91c6b039cb37cf 100644 (file)
@@ -2416,23 +2416,30 @@ tar_atol8(const char *p, unsigned char_cnt)
        limit = INT64_MAX / base;
        last_digit_limit = INT64_MAX % base;
 
-       while (*p == ' ' || *p == '\t')
+       while ((*p == ' ' || *p == '\t') && char_cnt != 0) {
                p++;
-       if (*p == '-') {
+               char_cnt--;
+       }
+
+       sign = 1;
+       if (char_cnt != 0 && *p == '-') {
                sign = -1;
                p++;
-       } else
-               sign = 1;
+               char_cnt--;
+       }
 
        l = 0;
-       digit = *p - '0';
-       while (digit >= 0 && digit < base  && char_cnt-- > 0) {
-               if (l>limit || (l == limit && digit > last_digit_limit)) {
-                       l = INT64_MAX; /* Truncate on overflow. */
-                       break;
+       if (char_cnt != 0) {
+               digit = *p - '0';
+               while (digit >= 0 && digit < base  && char_cnt != 0) {
+                       if (l>limit || (l == limit && digit > last_digit_limit)) {
+                               l = INT64_MAX; /* Truncate on overflow. */
+                               break;
+                       }
+                       l = (l * base) + digit;
+                       digit = *++p - '0';
+                       char_cnt--;
                }
-               l = (l * base) + digit;
-               digit = *++p - '0';
        }
        return (sign < 0) ? -l : l;
 }
@@ -2452,23 +2459,30 @@ tar_atol10(const char *p, unsigned char_cnt)
        limit = INT64_MAX / base;
        last_digit_limit = INT64_MAX % base;
 
-       while (*p == ' ' || *p == '\t')
+       while ((*p == ' ' || *p == '\t') && char_cnt != 0) {
                p++;
-       if (*p == '-') {
+               char_cnt--;
+       }
+
+       sign = 1;
+       if (char_cnt != 0 && *p == '-') {
                sign = -1;
                p++;
-       } else
-               sign = 1;
+               char_cnt--;
+       }
 
        l = 0;
-       digit = *p - '0';
-       while (digit >= 0 && digit < base  && char_cnt-- > 0) {
-               if (l > limit || (l == limit && digit > last_digit_limit)) {
-                       l = INT64_MAX; /* Truncate on overflow. */
-                       break;
+       if (char_cnt != 0) {
+               digit = *p - '0';
+               while (digit >= 0 && digit < base  && char_cnt != 0) {
+                       if (l > limit || (l == limit && digit > last_digit_limit)) {
+                               l = INT64_MAX; /* Truncate on overflow. */
+                               break;
+                       }
+                       l = (l * base) + digit;
+                       digit = *++p - '0';
+                       char_cnt--;
                }
-               l = (l * base) + digit;
-               digit = *++p - '0';
        }
        return (sign < 0) ? -l : l;
 }