aboutsummaryrefslogtreecommitdiff
path: root/lib/libarchive/archive_read_support_format_zip.c
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2010-11-07 03:40:37 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2010-11-07 03:40:37 +0000
commitf408e1d38d6cd5f22430d1db5032160e3472e099 (patch)
tree0e5ed8aa7a61822ccf502fc2862de80776098f05 /lib/libarchive/archive_read_support_format_zip.c
parent99b7f1da55e42ffbaaa2fa23914a15a321cff254 (diff)
Notes
Diffstat (limited to 'lib/libarchive/archive_read_support_format_zip.c')
-rw-r--r--lib/libarchive/archive_read_support_format_zip.c53
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;
}