summaryrefslogtreecommitdiff
path: root/libarchive/archive_read_support_format_tar.c
diff options
context:
space:
mode:
authorBrian Weaver <cmdrclueless@gmail.com>2012-09-25 09:51:12 -0400
committerBrian Weaver <cmdrclueless@gmail.com>2012-09-26 01:39:51 -0400
commitdb811950632784ce99d36c1c2402a021744df86a (patch)
tree36d3bdb8561354a57c951f640f64cda37adcd03e /libarchive/archive_read_support_format_tar.c
parent66b1a0b7a3b543f2e6f5ae9d59f3de04b80134a0 (diff)
downloadlibarchive-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.c58
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;
}