From: Joe Damato Date: Fri, 12 Oct 2018 00:40:45 +0000 (-0700) Subject: Handle ZIP files with padding in the extra fields X-Git-Tag: v3.4.0~19^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=353fc56c3bf3ed7ed7b183d41ddce74c830c29cc;p=thirdparty%2Flibarchive.git Handle ZIP files with padding in the extra fields Some ZIP files (certain android AAR packages) include ZIP extra fields that appear to be padded with 0s. This is technically incorrect, however other ZIP implementations appear to deal with these type of technically malformed files. It appears that these broken implementations may be padding the field to end on a word-aligned boundary. Instead of generating an error if the length of the extra field is less than the minimum size (4 bytes), consume the 1 - 3 bytes while checking that each byte is zero. If all bytes are zero, no error is raised. --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 420004dba..ddeda426d 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -428,10 +428,25 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct } if (extra_length < 4) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); - return ARCHIVE_FAILED; + size_t i = 0; + /* Some ZIP files may have trailing 0 bytes. Let's check they + * are all 0 and ignore them instead of returning an error. + * + * This is not techincally correct, but some ZIP files look like + * this and other tools support those files - so let's also + * support them. + */ + for (; i < extra_length; i++) { + if (p[i] != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); + return ARCHIVE_FAILED; + } + } + + return ARCHIVE_OK; } + while (offset <= extra_length - 4) { unsigned short headerid = archive_le16dec(p + offset); unsigned short datasize = archive_le16dec(p + offset + 2);