diff options
| author | Tim Kientzle <kientzle@FreeBSD.org> | 2010-11-07 03:40:37 +0000 |
|---|---|---|
| committer | Tim Kientzle <kientzle@FreeBSD.org> | 2010-11-07 03:40:37 +0000 |
| commit | f408e1d38d6cd5f22430d1db5032160e3472e099 (patch) | |
| tree | 0e5ed8aa7a61822ccf502fc2862de80776098f05 /lib/libarchive/archive_read_support_format_zip.c | |
| parent | 99b7f1da55e42ffbaaa2fa23914a15a321cff254 (diff) | |
Notes
Diffstat (limited to 'lib/libarchive/archive_read_support_format_zip.c')
| -rw-r--r-- | lib/libarchive/archive_read_support_format_zip.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c index 4a24cc80930b..0fa1fa391d58 100644 --- a/lib/libarchive/archive_read_support_format_zip.c +++ b/lib/libarchive/archive_read_support_format_zip.c @@ -128,6 +128,7 @@ static int archive_read_format_zip_read_data(struct archive_read *, static int archive_read_format_zip_read_data_skip(struct archive_read *a); static int archive_read_format_zip_read_header(struct archive_read *, struct archive_entry *); +static int search_next_signature(struct archive_read *); static int zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, off_t *offset); static int zip_read_data_none(struct archive_read *a, const void **buff, @@ -317,10 +318,17 @@ archive_read_format_zip_read_header(struct archive_read *a, signature = (const char *)h; } + /* If we don't see a PK signature here, scan forward. */ if (signature[0] != 'P' || signature[1] != 'K') { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Bad ZIP file"); - return (ARCHIVE_FATAL); + r = search_next_signature(a); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad ZIP file"); + return (ARCHIVE_FATAL); + } + if ((h = __archive_read_ahead(a, 4, NULL)) == NULL) + return (ARCHIVE_FATAL); + signature = (const char *)h; } /* @@ -375,6 +383,42 @@ archive_read_format_zip_read_header(struct archive_read *a, } static int +search_next_signature(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t skip; + ssize_t bytes; + int64_t skipped = 0; + + for (;;) { + h = __archive_read_ahead(a, 4, &bytes); + if (h == NULL) + return (ARCHIVE_FATAL); + p = h; + q = p + bytes; + + while (p + 4 <= q) { + if (p[0] == 'P' && p[1] == 'K') { + if ((p[2] == '\001' && p[3] == '\002') + || (p[2] == '\003' && p[3] == '\004') + || (p[2] == '\005' && p[3] == '\006') + || (p[2] == '\007' && p[3] == '\010') + || (p[2] == '0' && p[3] == '0')) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + } + ++p; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + skipped += skip; + } +} + +static int zip_read_file_header(struct archive_read *a, struct archive_entry *entry, struct zip *zip) { @@ -888,6 +932,9 @@ process_extra(const void* extra, struct zip* zip) if (datasize >= 4) zip->gid = archive_le16dec(p + offset + 2); break; + case 0x7875: + /* Info-Zip Unix Extra Field (type 3) "ux". */ + break; default: break; } |
