Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -609,13 +609,15 @@ - initWithStream: (OFStream *)stream { self = [super init]; @try { + void *pool = objc_autoreleasePoolPush(); + OFMutableData *extraField = nil; uint16_t fileNameLength, extraFieldLength; of_string_encoding_t encoding; - const uint8_t *ZIP64; + size_t ZIP64Index; uint16_t ZIP64Size; if ([stream readLittleEndianInt32] != 0x04034B50) @throw [OFInvalidFormatException exception]; @@ -633,27 +635,39 @@ ? OF_STRING_ENCODING_UTF_8 : OF_STRING_ENCODING_CODEPAGE_437); _fileName = [[stream readStringWithLength: fileNameLength encoding: encoding] copy]; - _extraField = - [[stream readDataWithCount: extraFieldLength] copy]; + if (extraFieldLength > 0) + extraField = [[[stream readDataWithCount: + extraFieldLength] mutableCopy] autorelease]; of_zip_archive_entry_extra_field_find(_extraField, - OF_ZIP_ARCHIVE_ENTRY_EXTRA_FIELD_ZIP64, &ZIP64, &ZIP64Size); + OF_ZIP_ARCHIVE_ENTRY_EXTRA_FIELD_ZIP64, &ZIP64Size); - if (ZIP64 != NULL) { + if (ZIP64Index != OF_NOT_FOUND) { + const uint8_t *ZIP64 = + [extraField itemAtIndex: ZIP64Index]; + if (_uncompressedSize == 0xFFFFFFFF) _uncompressedSize = of_zip_archive_read_field64( &ZIP64, &ZIP64Size); if (_compressedSize == 0xFFFFFFFF) _compressedSize = of_zip_archive_read_field64( &ZIP64, &ZIP64Size); if (ZIP64Size > 0) @throw [OFInvalidFormatException exception]; + + [extraField removeItemsInRange: + of_range(ZIP64Index - 4, ZIP64Size + 4)]; } + + [extraField makeImmutable]; + _extraField = [extraField copy]; + + objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } Index: src/OFZIPArchiveEntry.h ================================================================== --- src/OFZIPArchiveEntry.h +++ src/OFZIPArchiveEntry.h @@ -226,18 +226,18 @@ * specified tag. * * @param extraField The extra field to search for an extensible data field with * the specified tag * @param tag The tag to look for - * @param data A pointer to a pointer that should be set to the start of the - * extra field with the specified tag * @param size A pointer to an uint16_t that should be set to the size + * @return The index at which the extra field content starts in the OFData, or + * OF_NOT_FOUND */ -extern void of_zip_archive_entry_extra_field_find(OFData *extraField, - uint16_t tag, const uint8_t *_Nonnull *_Nonnull data, uint16_t *size); +extern size_t of_zip_archive_entry_extra_field_find(OFData *extraField, + uint16_t tag, uint16_t *size); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END #import "OFMutableZIPArchiveEntry.h" Index: src/OFZIPArchiveEntry.m ================================================================== --- src/OFZIPArchiveEntry.m +++ src/OFZIPArchiveEntry.m @@ -108,13 +108,13 @@ return [OFString stringWithFormat: @"%u.%u, unknown %02X", (version % 0xFF) / 10, (version & 0xFF) % 10, version >> 8]; } -void +size_t of_zip_archive_entry_extra_field_find(OFData *extraField, uint16_t tag, - const uint8_t **data, uint16_t *size) + uint16_t *size) { const uint8_t *bytes = [extraField items]; size_t count = [extraField count]; for (size_t i = 0; i < count;) { @@ -128,20 +128,19 @@ if (i + 3 + currentSize >= count) @throw [OFInvalidFormatException exception]; if (currentTag == tag) { - *data = bytes + i + 4; *size = currentSize; - return; + return i + 4; } i += 4 + currentSize; } - *data = NULL; *size = 0; + return OF_NOT_FOUND; } @implementation OFZIPArchiveEntry + (instancetype)entryWithFileName: (OFString *)fileName { @@ -178,13 +177,14 @@ { self = [super init]; @try { void *pool = objc_autoreleasePoolPush(); + OFMutableData *extraField = nil; uint16_t fileNameLength, extraFieldLength, fileCommentLength; of_string_encoding_t encoding; - const uint8_t *ZIP64 = NULL; + size_t ZIP64Index; uint16_t ZIP64Size; if ([stream readLittleEndianInt32] != 0x02014B50) @throw [OFInvalidFormatException exception]; @@ -210,21 +210,24 @@ : OF_STRING_ENCODING_CODEPAGE_437); _fileName = [[stream readStringWithLength: fileNameLength encoding: encoding] copy]; if (extraFieldLength > 0) - _extraField = - [[stream readDataWithCount: extraFieldLength] copy]; + extraField = [[[stream readDataWithCount: + extraFieldLength] mutableCopy] autorelease]; if (fileCommentLength > 0) _fileComment = [[stream readStringWithLength: fileCommentLength encoding: encoding] copy]; - of_zip_archive_entry_extra_field_find(_extraField, - OF_ZIP_ARCHIVE_ENTRY_EXTRA_FIELD_ZIP64, &ZIP64, &ZIP64Size); + ZIP64Index = of_zip_archive_entry_extra_field_find(_extraField, + OF_ZIP_ARCHIVE_ENTRY_EXTRA_FIELD_ZIP64, &ZIP64Size); - if (ZIP64 != NULL) { + if (ZIP64Index != OF_NOT_FOUND) { + const uint8_t *ZIP64 = + [_extraField itemAtIndex: ZIP64Index]; + if (_uncompressedSize == 0xFFFFFFFF) _uncompressedSize = of_zip_archive_read_field64( &ZIP64, &ZIP64Size); if (_compressedSize == 0xFFFFFFFF) _compressedSize = of_zip_archive_read_field64( @@ -237,12 +240,18 @@ _startDiskNumber = of_zip_archive_read_field32( &ZIP64, &ZIP64Size); if (ZIP64Size > 0 || _localFileHeaderOffset < 0) @throw [OFInvalidFormatException exception]; + + [extraField removeItemsInRange: + of_range(ZIP64Index - 4, ZIP64Size + 4)]; } + [extraField makeImmutable]; + _extraField = [extraField copy]; + objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; }