summaryrefslogtreecommitdiffstats
path: root/contrib/libarchive/libarchive/archive_read_support_format_tar.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libarchive/libarchive/archive_read_support_format_tar.c')
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_tar.c96
1 files changed, 42 insertions, 54 deletions
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_tar.c b/contrib/libarchive/libarchive/archive_read_support_format_tar.c
index 867d208..fde339a 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_tar.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_tar.c
@@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *,
struct archive_string *, const void *h, size_t *);
static int solaris_sparse_parse(struct archive_read *, struct tar *,
struct archive_entry *, const char *);
-static int64_t tar_atol(const char *, unsigned);
-static int64_t tar_atol10(const char *, unsigned);
-static int64_t tar_atol256(const char *, unsigned);
-static int64_t tar_atol8(const char *, unsigned);
+static int64_t tar_atol(const char *, size_t);
+static int64_t tar_atol10(const char *, size_t);
+static int64_t tar_atol256(const char *, size_t);
+static int64_t tar_atol8(const char *, size_t);
static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, size_t *);
static int tohex(int c);
@@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_header,
archive_read_format_tar_read_data,
archive_read_format_tar_skip,
+ NULL,
archive_read_format_tar_cleanup);
if (r != ARCHIVE_OK)
@@ -616,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar,
int err;
const char *h;
const struct archive_entry_header_ustar *header;
+ const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
- return (bytes);
+ return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
@@ -703,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
err = header_pax_extensions(a, tar, entry, h, unconsumed);
break;
default:
- if (memcmp(header->magic, "ustar \0", 8) == 0) {
+ gnuheader = (const struct archive_entry_header_gnutar *)h;
+ if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err = header_gnutar(a, tar, entry, h, unconsumed);
@@ -752,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
- return (bytes_read);
+ return ((int)bytes_read);
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -2392,7 +2395,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
* On read, this implementation supports both extensions.
*/
static int64_t
-tar_atol(const char *p, unsigned char_cnt)
+tar_atol(const char *p, size_t char_cnt)
{
/*
* Technically, GNU tar considers a field to be in base-256
@@ -2409,70 +2412,55 @@ tar_atol(const char *p, unsigned char_cnt)
* it does obey locale.
*/
static int64_t
-tar_atol8(const char *p, unsigned char_cnt)
+tar_atol_base_n(const char *p, size_t char_cnt, int base)
{
int64_t l, limit, last_digit_limit;
- int digit, sign, base;
+ int digit, sign;
- base = 8;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
- while (*p == ' ' || *p == '\t')
+ /* the pointer will not be dereferenced if char_cnt is zero
+ * due to the way the && operator is evaulated.
+ */
+ while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
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;
}
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
static int64_t
-tar_atol10(const char *p, unsigned char_cnt)
+tar_atol8(const char *p, size_t char_cnt)
{
- int64_t l, limit, last_digit_limit;
- int base, digit, sign;
-
- base = 10;
- limit = INT64_MAX / base;
- last_digit_limit = INT64_MAX % base;
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '-') {
- sign = -1;
- p++;
- } else
- sign = 1;
+ return tar_atol_base_n(p, char_cnt, 8);
+}
- 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;
- }
- l = (l * base) + digit;
- digit = *++p - '0';
- }
- return (sign < 0) ? -l : l;
+static int64_t
+tar_atol10(const char *p, size_t char_cnt)
+{
+ return tar_atol_base_n(p, char_cnt, 10);
}
/*
@@ -2481,7 +2469,7 @@ tar_atol10(const char *p, unsigned char_cnt)
* ignored.
*/
static int64_t
-tar_atol256(const char *_p, unsigned char_cnt)
+tar_atol256(const char *_p, size_t char_cnt)
{
int64_t l, upper_limit, lower_limit;
const unsigned char *p = (const unsigned char *)_p;
OpenPOWER on IntegriCloud