From 231c9c716855c65b389460e328cec5f81c269f05 Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Thu, 17 Dec 2015 01:26:38 +0100 Subject: [PATCH] Really parse the extra field seeking for ZIP64 extended data Extended ZIP64 data are stored in the field with Header ID = 1 and we need to iterate over all fields to find it because it is not stated in the documentation the it must be the first record in the collection. wxZipHeader is designed to process standard 64-byte headers and it is safe to use it to process data in the field with Header ID = 1 which can have up to 28 bytes. Closes #17170. --- src/common/zipstrm.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/common/zipstrm.cpp b/src/common/zipstrm.cpp index 54824b3572..a662a4438e 100644 --- a/src/common/zipstrm.cpp +++ b/src/common/zipstrm.cpp @@ -1016,22 +1016,36 @@ void wxZipEntry::UnsetNotifier() bool wxZipEntry::LoadExtraInfo(const char* extraData, wxUint16 extraLen, bool localInfo) { - wxZipHeader ds(extraData, extraLen); - - // A file may contain larger size, compressed size or offset - // in a zip64 extra data block. Use the 64 bit values if available - if ( extraLen > 4 && ds.Read16() == 1 ) + // We need to iterate over all headers + // seeking for the field with Header ID = 1. + // (There is not stated in the documentation + // that it should be the first one in the collection.) + while ( extraLen >= 4 ) { - ds.Read16(); // skip record size - if ( m_Size == 0xffffffff ) - m_Size = ds.Read64(); - if ( m_CompressedSize == 0xffffffff ) - m_CompressedSize = ds.Read64(); - if ( !localInfo && m_Offset == 0xffffffff ) - m_Offset = ds.Read64(); + // Parse extra header + wxZipHeader hds(extraData, 4); + wxUint16 fieldID = hds.Read16(); + wxUint16 fieldLen = hds.Read16(); + if ( fieldID == 1 ) + { + // Data block for extra field with Header ID = 1 (ZIP64) + // can have length up to 28 bytes. + wxZipHeader ds(extraData+4, wxMin(fieldLen, 28)); + // A file may contain larger size, compressed size or offset + // in a zip64 extra data block. Use the 64 bit values if available + if ( m_Size == 0xffffffff ) + m_Size = ds.Read64(); + if ( m_CompressedSize == 0xffffffff ) + m_CompressedSize = ds.Read64(); + if ( !localInfo && m_Offset == 0xffffffff ) + m_Offset = ds.Read64(); + // extraInfo was used and parsed + return true; + } - // extraInfo was used and parsed - return true; + fieldLen += 4; + extraData += fieldLen; + extraLen -= fieldLen; } // extraInfo had unknown format