From b0eb750cabc9bdd4fba38d3efd1b747a7cd967de Mon Sep 17 00:00:00 2001 From: Brian Weaver Date: Tue, 25 Sep 2012 09:51:12 -0400 Subject: [PATCH] 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. --- libarchive/archive_read_support_format_tar.c | 52 +++++++++++--------- 1 file changed, 30 insertions(+), 22 deletions(-) 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; } -- 2.47.2