From: Brian Weaver Date: Tue, 25 Sep 2012 13:51:12 +0000 (-0400) Subject: Add tighter checks to avoid reading past end of buffer X-Git-Tag: v3.1.0~47^2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F24%2Fhead;p=thirdparty%2Flibarchive.git Add tighter checks to avoid reading past end of buffer 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. --- diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 4538331f3..8186d2738 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -2416,23 +2416,27 @@ tar_atol8(const char *p, unsigned char_cnt) limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; - while (*p == ' ' || *p == '\t') + while (char_cnt-- > 0 && (*p == ' ' || *p == '\t')) p++; - if (*p == '-') { + + 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'; } - l = (l * base) + digit; - digit = *++p - '0'; } return (sign < 0) ? -l : l; } @@ -2452,23 +2456,27 @@ tar_atol10(const char *p, unsigned char_cnt) limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; - while (*p == ' ' || *p == '\t') + while (char_cnt-- > 0 && (*p == ' ' || *p == '\t')) p++; - if (*p == '-') { + + 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'; } - l = (l * base) + digit; - digit = *++p - '0'; } return (sign < 0) ? -l : l; }