diff options
author | Brian Weaver <cmdrclueless@gmail.com> | 2012-09-25 09:51:12 -0400 |
---|---|---|
committer | Brian Weaver <cmdrclueless@gmail.com> | 2012-09-26 01:39:51 -0400 |
commit | db811950632784ce99d36c1c2402a021744df86a (patch) | |
tree | 36d3bdb8561354a57c951f640f64cda37adcd03e /libarchive/archive_read_support_format_tar.c | |
parent | 66b1a0b7a3b543f2e6f5ae9d59f3de04b80134a0 (diff) | |
download | libarchive-db811950632784ce99d36c1c2402a021744df86a.tar.gz |
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.
successfully passes 'make check-TESTS'
Diffstat (limited to 'libarchive/archive_read_support_format_tar.c')
-rw-r--r-- | libarchive/archive_read_support_format_tar.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 4538331f..ed579933 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -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; } |