You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by ar...@apache.org on 2026/03/30 16:48:16 UTC

(openoffice) branch trunk updated: Correct possible issues with ZIP files

This is an automated email from the ASF dual-hosted git repository.

ardovm pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1972b29432 Correct possible issues with ZIP files
1972b29432 is described below

commit 1972b29432a5b05e40ec16d939ddb345b981e240
Author: Arrigo Marchiori <ar...@yahoo.it>
AuthorDate: Thu Mar 12 19:18:44 2026 +0100

    Correct possible issues with ZIP files
---
 main/comphelper/source/misc/storagehelper.cxx      |   2 +-
 main/package/inc/ZipEntry.hxx                      |  38 ++-
 main/package/inc/ZipFile.hxx                       |  10 +
 .../source/package/zipapi/XUnbufferedStream.cxx    |   6 +-
 main/package/source/package/zipapi/ZipFile.cxx     | 276 +++++++++++++++++----
 .../source/package/zipapi/ZipOutputStream.cxx      |  52 ++--
 .../source/package/zippackage/ZipPackage.cxx       |   5 +
 .../source/package/zippackage/ZipPackageFolder.cxx |  15 +-
 .../source/package/zippackage/ZipPackageStream.cxx |  14 +-
 9 files changed, 331 insertions(+), 87 deletions(-)

diff --git a/main/comphelper/source/misc/storagehelper.cxx b/main/comphelper/source/misc/storagehelper.cxx
index 0c4a1da91c..140e99b299 100644
--- a/main/comphelper/source/misc/storagehelper.cxx
+++ b/main/comphelper/source/misc/storagehelper.cxx
@@ -506,7 +506,7 @@ sal_Bool OStorageHelper::IsValidZipEntryFileName(
             case ':':
                 return sal_False;
             case '/':
-                if ( !bSlashAllowed )
+                if ( ( i == 0 ) || !bSlashAllowed )
                     return sal_False;
                 break;
             default:
diff --git a/main/package/inc/ZipEntry.hxx b/main/package/inc/ZipEntry.hxx
index ffa3c79931..c06efacb44 100644
--- a/main/package/inc/ZipEntry.hxx
+++ b/main/package/inc/ZipEntry.hxx
@@ -25,18 +25,52 @@
 
 #include <rtl/ustring.hxx>
 
+/// Data from a central directory header.
 struct ZipEntry
 {
+    /// version needed to extract
     sal_Int16 nVersion;
+    /// general purpose bit flag
     sal_Int16 nFlag;
+    /// compression method
     sal_Int16 nMethod;
+    /// last mod file date & time
     sal_Int32 nTime;
+    /// crc-32
     sal_Int32 nCrc;
+    /// compressed size
     sal_Int32 nCompressedSize;
+    /// uncompressed size
     sal_Int32 nSize;
-    sal_Int32 nOffset;
+    /// (Absolute) offset to the local file header
+    sal_Int32 nFileHeaderOffset;
+    /// (Absolute) offset to the file data
+    sal_Int32 nFileDataOffset;
+    /// file name length
     sal_Int16 nPathLen;
-    sal_Int16 nExtraLen;
+    /// extra field length of local file header
+    sal_Int16 nLOCExtraLen;
+    /// extra field length of central directory header
+    sal_Int16 nCENExtraLen;
+    /// file name
     ::rtl::OUString sPath;
+    /// True if the entry has a data descriptor after the file data
+    sal_Bool bHasDataDescriptor;
+    /// Default constructor
+    ZipEntry():
+        nVersion(-1),
+        nFlag(0),
+        nMethod(0),
+        nTime(-1),
+        nCrc(0),
+        nCompressedSize(0),
+        nSize(0),
+        nFileHeaderOffset(-1),
+        nFileDataOffset(-1),
+        nPathLen(0),
+        nLOCExtraLen(0),
+        nCENExtraLen(0),
+        bHasDataDescriptor(sal_False) {
+    }
 };
 #endif
diff --git a/main/package/inc/ZipFile.hxx b/main/package/inc/ZipFile.hxx
index 51c1c322a2..340a566cb4 100644
--- a/main/package/inc/ZipFile.hxx
+++ b/main/package/inc/ZipFile.hxx
@@ -194,10 +194,20 @@ public:
 
     ZipEnumeration * SAL_CALL entries(  );
 protected:
+	/** Decode a local file header of an entry and update a ZipEntry
+	 *
+	 * @param rEntry entry with the nFileHeaderOffset field populated. At return, the ZipEntry::nFileDataOffset and ZipEntry::nLOCExtraLen fields will be set.
+	 *
+	 * Also searches for a data descriptor after the file data and validates it.
+	 *
+	 * @return sal_True if successful, otherwise throws exceptions.
+	 */
 	sal_Bool		readLOC ( ZipEntry &rEntry)
 		throw(::com::sun::star::io::IOException, com::sun::star::packages::zip::ZipException, com::sun::star::uno::RuntimeException);
+	/// Decode the End of central directory record
 	sal_Int32		readCEN()
 		throw(::com::sun::star::io::IOException, com::sun::star::packages::zip::ZipException, com::sun::star::uno::RuntimeException);
+	/// Find the End of central directory record
 	sal_Int32		findEND()
 		throw(::com::sun::star::io::IOException, com::sun::star::packages::zip::ZipException, com::sun::star::uno::RuntimeException);
 	sal_Int32 		recover()
diff --git a/main/package/source/package/zipapi/XUnbufferedStream.cxx b/main/package/source/package/zipapi/XUnbufferedStream.cxx
index f4f38978b6..accf8caa3c 100644
--- a/main/package/source/package/zipapi/XUnbufferedStream.cxx
+++ b/main/package/source/package/zipapi/XUnbufferedStream.cxx
@@ -80,16 +80,16 @@ XUnbufferedStream::XUnbufferedStream(
 , mnMyCurrent ( 0 )
 , mbCheckCRC( !bRecoveryMode )
 {
-	mnZipCurrent = maEntry.nOffset;
+	mnZipCurrent = maEntry.nFileDataOffset;
 	if ( mbRawStream )
 	{
 		mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
-		mnZipEnd = maEntry.nOffset + mnZipSize;
+		mnZipEnd = maEntry.nFileDataOffset + mnZipSize;
 	}
 	else
 	{
 		mnZipSize = maEntry.nSize;
-		mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
+		mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nFileDataOffset + maEntry.nCompressedSize : maEntry.nFileDataOffset + maEntry.nSize;
 	}
 	sal_Bool bHaveEncryptData = ( rData.is() && rData->m_aSalt.getLength() && rData->m_aInitVector.getLength() && rData->m_nIterationCount != 0 ) ? sal_True : sal_False;
 	sal_Bool bMustDecrypt = ( nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False;
diff --git a/main/package/source/package/zipapi/ZipFile.cxx b/main/package/source/package/zipapi/ZipFile.cxx
index 1e0ca9ee8b..c58ef3bd0a 100644
--- a/main/package/source/package/zipapi/ZipFile.cxx
+++ b/main/package/source/package/zipapi/ZipFile.cxx
@@ -498,7 +498,7 @@ sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference<
 	sal_Bool bRet = sal_False;
 	if ( rData.is() && rData->m_aKey.getLength() )
 	{
-		xSeek->seek( rEntry.nOffset );
+		xSeek->seek( rEntry.nFileDataOffset );
 		sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
 
 		// Only want to read enough to verify the digest
@@ -523,6 +523,10 @@ uno::Reference< XInputStream > ZipFile::createUnbufferedStream(
 			sal_Bool bIsEncrypted,
 			::rtl::OUString aMediaType )
 {
+
+	// Only encrypted entries can be STORED and have a data descriptor
+	if ( !bIsEncrypted && ( rEntry.nMethod == STORED ) && rEntry.bHasDataDescriptor )
+		throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "entry has spurious file descriptor" ) ), uno::Reference < XInterface > () );
     ::osl::MutexGuard aGuard( m_aMutex );
 
 	return new XUnbufferedStream ( m_xFactory, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode );
@@ -542,7 +546,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntr
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
-	if ( rEntry.nOffset <= 0 )
+	if ( rEntry.nFileDataOffset <= 0 )
 		readLOC( rEntry );
 
 	// We want to return a rawStream if we either don't have a key or if the
@@ -573,7 +577,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
-	if ( rEntry.nOffset <= 0 )
+	if ( rEntry.nFileDataOffset <= 0 )
 		readLOC( rEntry );
 
 	// An exception must be thrown in case stream is encrypted and
@@ -611,7 +615,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry,
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
-	if ( rEntry.nOffset <= 0 )
+	if ( rEntry.nFileDataOffset <= 0 )
 		readLOC( rEntry );
 
 	return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
@@ -632,20 +636,63 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream(
 	if ( !rData.is() )
 		throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
 
-	if ( rEntry.nOffset <= 0 )
+	if ( rEntry.nFileDataOffset <= 0 )
 		readLOC( rEntry );
 
 	return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, sal_True, aMediaType );
 }
 
+/** Read extra fields
+ *
+ * @param rGrabber Grabber object for reading data.
+ * @param nLength extra field length
+ * @param rEntry entry data.
+ *
+ * Expects rGrabber to point to the beginning of the extra fields.
+ * Advances it until all fields are read (i.e. after nLength bytes).
+ *
+ * @throw ZipException in case of problems.
+ */
+static void readExtraFields( MemoryByteGrabber &rMemGrabber, sal_Int16 nLength, ZipEntry &rEntry )
+{
+	sal_Int16 nHeaderID, nDataSize;
+	sal_Int16 nReadBytes = 0;
+	sal_Int8 n8;
+	rtl::OUString s;
+	while ( ( nLength - nReadBytes ) >= 2 ) {
+		rMemGrabber >> nHeaderID;
+		rMemGrabber >> nDataSize;
+		nReadBytes += 2;
+		if (( nDataSize > ( nLength - nReadBytes ) ) ||
+			( nDataSize > rMemGrabber.available() ) )
+			throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid ZIP extra fields" ) ), uno::Reference < XInterface > () );
+		switch ( nHeaderID ) {
+		case 0x7075: // Info-ZIP Unicode Path Extra Field
+			rMemGrabber >> n8; // Version
+			rMemGrabber.skipBytes( 4 ); // skip NameCRC32
+			s = rtl::OUString::intern ( (sal_Char *) rMemGrabber.getCurrentPos(),
+										nDataSize - 5,
+										RTL_TEXTENCODING_UTF8 );
+			if ( n8 != 1 )
+				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid ZIP unicode path extra field version" ) ), uno::Reference < XInterface > () );
+			if ( s != rEntry.sPath )
+				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid ZIP unicode path extra field" ) ), uno::Reference < XInterface > () );
+			rMemGrabber.skipBytes( nDataSize - 5 );
+			break;
+		default:  // We are not interested in this field
+			rMemGrabber.skipBytes( nDataSize );
+		}
+	}
+}
+
 sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
 	throw(IOException, ZipException, RuntimeException)
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
 	sal_Int32 nTestSig, nTime, nCRC, nSize, nCompressedSize;
-	sal_Int16 nVersion, nFlag, nHow, nPathLen, nExtraLen;
-	sal_Int32 nPos = -rEntry.nOffset;
+	sal_Int16 nVersion, nFlag, nHow, nPathLen;
+	sal_Int32 nPos = rEntry.nFileHeaderOffset;
 
 	aGrabber.seek(nPos);
 	aGrabber >> nTestSig;
@@ -660,8 +707,8 @@ sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
 	aGrabber >> nCompressedSize;
 	aGrabber >> nSize;
 	aGrabber >> nPathLen;
-	aGrabber >> nExtraLen;
-	rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nPathLen + nExtraLen;
+	aGrabber >> rEntry.nLOCExtraLen;
+	rEntry.nFileDataOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nPathLen + rEntry.nLOCExtraLen;
 
     // read always in UTF8, some tools seem not to set UTF8 bit
     uno::Sequence < sal_Int8 > aNameBuffer( nPathLen );
@@ -682,6 +729,7 @@ sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
 	// the method can be reset for internal use so it is not checked
 	sal_Bool bBroken = rEntry.nVersion != nVersion
 					|| rEntry.nFlag != nFlag
+					|| rEntry.nMethod != nHow
 					|| rEntry.nTime != nTime
 					|| rEntry.nPathLen != nPathLen
                     || !rEntry.sPath.equals( sLOCPath );
@@ -690,6 +738,37 @@ sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
 		throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
 							uno::Reference< XInterface >() );
 
+	Sequence < sal_Int8 > aExtraFields ( rEntry.nLOCExtraLen );
+	nRead = aGrabber.readBytes( aExtraFields, rEntry.nLOCExtraLen );
+	if ( nRead != rEntry.nLOCExtraLen )
+		throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Error reading LOC extra fields into memory buffer!") ), uno::Reference < XInterface > () );
+	MemoryByteGrabber aMemGrabber ( aExtraFields );
+	readExtraFields( aMemGrabber, rEntry.nLOCExtraLen, rEntry );
+
+	// Check for a data descriptor
+	rEntry.bHasDataDescriptor = rEntry.nFlag & ( 1 << 3 );
+	if ( rEntry.bHasDataDescriptor ) {
+		// some fields of the local file header must be zero
+		if ( ( nCRC | nCompressedSize | nSize ) != 0 )
+			throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Data descriptor mismatch!") ), uno::Reference < XInterface > () );
+	}
+	sal_Int32 n32;
+	aGrabber.seek( rEntry.nFileDataOffset + rEntry.nCompressedSize );
+	aGrabber >> n32;
+	if ( n32 == EXTSIG ) { // Signature detected
+		rEntry.bHasDataDescriptor = sal_True;
+		aGrabber >> n32;
+	}
+	if ( rEntry.bHasDataDescriptor ) {
+		if ( n32 != rEntry.nCrc )
+			throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Data descriptor CRC mismatch!") ), uno::Reference < XInterface > () );
+		aGrabber >> n32;
+		if ( n32 != rEntry.nCompressedSize )
+			throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Data descriptor compressed size mismatch!") ), uno::Reference < XInterface > () );
+		aGrabber >> n32;
+		if ( n32 != rEntry.nSize )
+			throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Data descriptor uncompressed size mismatch!") ), uno::Reference < XInterface > () );
+	}
 	return sal_True;
 }
 
@@ -735,6 +814,18 @@ sal_Int32 ZipFile::findEND( )
 	throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
 }
 
+static sal_Bool entriesContainPath( const EntryHash &rEntries,
+									const OUString &sPath )
+{
+	for ( EntryHash::const_iterator aIt = rEntries.begin();
+		  aIt != rEntries.end(); ++aIt)
+	{
+		if ( aIt->first.equalsIgnoreAsciiCase( sPath ) )
+			return sal_True;
+	}
+	return sal_False;
+}
+
 sal_Int32 ZipFile::readCEN()
 	throw(IOException, ZipException, RuntimeException)
 {
@@ -747,9 +838,18 @@ sal_Int32 ZipFile::readCEN()
 		nEndPos = findEND();
 		if (nEndPos == -1)
 			return -1;
+		/*
+		  Ignored fields:
+		   - number of this disk
+		   - number of the disk with the start of the central directory
+		   - total number of entries in the central directory on this disk
+		*/
 		aGrabber.seek(nEndPos + ENDTOT);
+		// total number of entries in the central directory
 		aGrabber >> nTotal;
+		// size of the central directory
 		aGrabber >> nCenLen;
+		// offset of start of central directory
 		aGrabber >> nCenOff;
 
 		if ( nTotal * CENHDR > nCenLen )
@@ -766,6 +866,7 @@ sal_Int32 ZipFile::readCEN()
 		if ( nCenOff < 0 || nCenOff > nCenPos )
 			throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference < XInterface > () );
 
+		// Read the central directory headers
 		nLocPos = nCenPos - nCenOff;
 		aGrabber.seek( nCenPos );
 		Sequence < sal_Int8 > aCENBuffer ( nCenLen );
@@ -778,6 +879,7 @@ sal_Int32 ZipFile::readCEN()
 		ZipEntry aEntry;
 		sal_Int32 nTestSig;
 		sal_Int16 nCommentLen;
+		rtl::OUString sFirstFilePath;
 
 		for (nCount = 0 ; nCount < nTotal; nCount++)
 		{
@@ -785,30 +887,31 @@ sal_Int32 ZipFile::readCEN()
 			if ( nTestSig != CENSIG )
 				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), uno::Reference < XInterface > () );
 
-			aMemGrabber.skipBytes ( 2 );
-			aMemGrabber >> aEntry.nVersion;
-
-			if ( ( aEntry.nVersion & 1 ) == 1 )
+			aMemGrabber.skipBytes ( 2 ); // skip: versione made by
+			aMemGrabber >> aEntry.nVersion; // version needed to extract
+			aMemGrabber >> aEntry.nFlag; // general purpose bit flag
+			if ( ( aEntry.nFlag & 1 ) == 1 )
 				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), uno::Reference < XInterface > () );
 
-			aMemGrabber >> aEntry.nFlag;
-			aMemGrabber >> aEntry.nMethod;
+			aMemGrabber >> aEntry.nMethod; // compression method
 
 			if ( aEntry.nMethod != STORED && aEntry.nMethod != DEFLATED)
 				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), uno::Reference < XInterface > () );
 
-			aMemGrabber >> aEntry.nTime;
-			aMemGrabber >> aEntry.nCrc;
-			aMemGrabber >> aEntry.nCompressedSize;
-			aMemGrabber >> aEntry.nSize;
-			aMemGrabber >> aEntry.nPathLen;
-			aMemGrabber >> aEntry.nExtraLen;
-			aMemGrabber >> nCommentLen;
+			aMemGrabber >> aEntry.nTime; // last mod file date & time
+			aMemGrabber >> aEntry.nCrc; // crc-32
+			aMemGrabber >> aEntry.nCompressedSize; // compressed size
+			aMemGrabber >> aEntry.nSize; // uncompressed size
+			if ( aEntry.nMethod == STORED && ( aEntry.nCompressedSize != aEntry.nSize ) )
+				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Size mismatch of STORED entry") ), uno::Reference < XInterface > () );
+			aMemGrabber >> aEntry.nPathLen; // file name length
+			aMemGrabber >> aEntry.nCENExtraLen; // extra field length
+			aMemGrabber >> nCommentLen; // file comment length
+			// skip: disk number start, internal & external file attributes
 			aMemGrabber.skipBytes ( 8 );
-			aMemGrabber >> aEntry.nOffset;
+			aMemGrabber >> aEntry.nFileHeaderOffset; // relative offset of local header
 
-			aEntry.nOffset += nLocPos;
-			aEntry.nOffset *= -1;
+			aEntry.nFileHeaderOffset += nLocPos;
 
 			if ( aEntry.nPathLen < 0 )
 				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected name length" ) ), uno::Reference < XInterface > () );
@@ -816,23 +919,103 @@ sal_Int32 ZipFile::readCEN()
 			if ( nCommentLen < 0 )
 				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected comment length" ) ), uno::Reference < XInterface > () );
 
-			if ( aEntry.nExtraLen < 0 )
+			if ( aEntry.nCENExtraLen < 0 )
 				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected extra header info length") ), uno::Reference < XInterface > () );
 
-            // read always in UTF8, some tools seem not to set UTF8 bit
+            // read file name always in UTF8, some tools seem not to set UTF8 bit
 			aEntry.sPath = rtl::OUString::intern ( (sal_Char *) aMemGrabber.getCurrentPos(),
                                                    aEntry.nPathLen,
                                                    RTL_TEXTENCODING_UTF8 );
 
             if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aEntry.sPath, sal_True ) )
 				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip entry has an invalid name.") ), uno::Reference < XInterface > () );
-
-			aMemGrabber.skipBytes( aEntry.nPathLen + aEntry.nExtraLen + nCommentLen );
+			// Simplify path removing leading "./"
+			while ( aEntry.sPath.compareToAscii( "./", 2 ) == 0 )
+				aEntry.sPath = aEntry.sPath.copy( 2 );
+
+			// skip: file name (already processed)
+			aMemGrabber.skipBytes( aEntry.nPathLen );
+			readExtraFields( aMemGrabber, aEntry.nCENExtraLen, aEntry );
+			// Search for Zip64 data among the comments.
+			// The Zip64 EOCDL takes 20 bytes; the ZIP64 EOCDR takes > 56 bytes
+			const sal_Int8* pCommentStart = aMemGrabber.getCurrentPos();
+			for ( const sal_Int8* pCommentEnd = pCommentStart + nCommentLen;
+				  pCommentEnd >= ( pCommentStart + 76 );
+				  --pCommentEnd) {
+				const sal_Int8 * p = ( pCommentEnd - 20 );
+				sal_Int32 n32;
+				if (p[0] == 0x50)
+				// Detect EOCDL signature 0x07064b50
+				if ( ( p[0] == 0x50 ) &&
+					 ( p[1] == 0x4b ) &&
+					 ( p[2] == 0x06 ) &&
+					 ( p[3] == 0x07 ) ) {
+					// the relative offset of the zip64 end of central directory record starts at offset 8...
+					n32 = p[8] | ( p[9] << 8 ) | ( p[10] << 16 ) |
+						( p[11] << 24 );
+					// ...and it must be a 32-bit number represented with 64 bits
+					if ( ( p[12] | p[13] | p[14] | p[15] ) == 0 ) {
+						n32 -= nCenPos + aMemGrabber.getPosition();
+						// Detect EOCDR signature 0x06064b50
+						if ( ( n32 > 0 ) &&
+							 ( pCommentStart[n32] == 0x50 ) &&
+							 ( pCommentStart[n32 + 1] == 0x4b ) &&
+							 ( pCommentStart[n32 + 2] == 0x06 ) &&
+							 ( pCommentStart[n32 + 3] == 0x06 ) ) {
+								throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Zip64 data found inside comments section") ), uno::Reference < XInterface > () );
+						}
+					}
+				}
+			}
+			aMemGrabber.skipBytes( nCommentLen );
+			if ( entriesContainPath( aEntries, aEntry.sPath ) )
+				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Duplicated zip entry") ), uno::Reference < XInterface > () );
+			readLOC( aEntry );
+			if ( aEntry.nFileHeaderOffset == 0 )
+				sFirstFilePath = aEntry.sPath;
 			aEntries[aEntry.sPath] = aEntry;
 		}
 
 		if (nCount != nTotal)
 			throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), uno::Reference < XInterface > () );
+
+		if ( sFirstFilePath.getLength() == 0 )
+			throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "File contains junk before compressed data" ) ), uno::Reference < XInterface > () );
+
+		// Verify the proper sequence of fields
+		sal_Int32 nPos, nPos2;
+		EntryHash::const_iterator aIt = aEntries.find( sFirstFilePath );
+		nCount = 0;
+		nPos = 0;
+		do {
+			if ( aIt == aEntries.end() ) throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Internal error" ) ), uno::Reference < XInterface > () );
+			// Local file header
+			nPos += 30 + aIt->first.getLength() + aIt->second.nLOCExtraLen;
+			if ( nPos != aIt->second.nFileDataOffset )
+				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "ZIP file contains a hole between local descriptor and file data" ) ), uno::Reference < XInterface > () );
+			// File data
+			nPos += aIt->second.nCompressedSize;
+			if ( aIt->second.nFlag & ( 1 << 3 ) ) {
+				// Data descriptor...
+				nPos += 16;  // ...with signature
+				nPos2 = nPos - 4; // ...without signature
+			} else nPos2 = nPos;
+			++nCount;
+			if ( nCount == nTotal ) {
+				break;
+			}
+			// Find next entry, starting at either nPos or nPos2
+			for ( aIt = aEntries.begin(); aIt != aEntries.end(); ++aIt )
+				if (( aIt->second.nFileHeaderOffset == nPos ) ||
+					( aIt->second.nFileHeaderOffset == nPos2 ))
+					break;
+			if ( aIt == aEntries.end() )
+				throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "ZIP file contains holes among files" ) ), uno::Reference < XInterface > () );
+			nPos = aIt->second.nFileHeaderOffset;
+		} while ( 1 );
+		// After all files, we should have arrived at the central directory header
+		if ( nPos != nCenPos )
+			throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "ZIP file contains a hole before the central directory" ) ), uno::Reference < XInterface > () );
 	}
 	catch ( IllegalArgumentException & )
 	{
@@ -874,13 +1057,14 @@ sal_Int32 ZipFile::recover()
 			{
 				if ( nPos < nBufSize - 30 && pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 3 && pBuffer[nPos+3] == 4 )
 				{
+					// Local file header
 					ZipEntry aEntry;
 					MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 26 ) );
 
 					aMemGrabber >> aEntry.nVersion;
-					if ( ( aEntry.nVersion & 1 ) != 1 )
+					aMemGrabber >> aEntry.nFlag;
+					if ( ( aEntry.nFlag & 1 ) != 1 ) // Must not be encrypted
 					{
-						aMemGrabber >> aEntry.nFlag;
 						aMemGrabber >> aEntry.nMethod;
 
 						if ( aEntry.nMethod == STORED || aEntry.nMethod == DEFLATED )
@@ -890,7 +1074,7 @@ sal_Int32 ZipFile::recover()
 							aMemGrabber >> aEntry.nCompressedSize;
 							aMemGrabber >> aEntry.nSize;
 							aMemGrabber >> aEntry.nPathLen;
-							aMemGrabber >> aEntry.nExtraLen;
+							aMemGrabber >> aEntry.nLOCExtraLen;
 
 							sal_Int32 nDescrLength =
 								( aEntry.nMethod == DEFLATED && ( aEntry.nFlag & 8 ) ) ?
@@ -902,12 +1086,12 @@ sal_Int32 ZipFile::recover()
 							if ( aEntry.nCompressedSize < 0 ) aEntry.nCompressedSize = 0x7FFFFFFF;
 							if ( aEntry.nSize < 0 ) aEntry.nSize = 0x7FFFFFFF;
 							if ( aEntry.nPathLen < 0 ) aEntry.nPathLen = 0x7FFF;
-							if ( aEntry.nExtraLen < 0 ) aEntry.nExtraLen = 0x7FFF;
+							if ( aEntry.nLOCExtraLen < 0 ) aEntry.nLOCExtraLen = 0x7FFF;
 							// End of quick fix
 
 							sal_Int32 nDataSize = ( aEntry.nMethod == DEFLATED ) ? aEntry.nCompressedSize : aEntry.nSize;
-							sal_Int32 nBlockLength = nDataSize + aEntry.nPathLen + aEntry.nExtraLen + 30 + nDescrLength;
-							if ( aEntry.nPathLen >= 0 && aEntry.nExtraLen >= 0
+							sal_Int32 nBlockLength = nDataSize + aEntry.nPathLen + aEntry.nLOCExtraLen + 30 + nDescrLength;
+							if ( aEntry.nPathLen >= 0 && aEntry.nLOCExtraLen >= 0
 								&& ( nGenPos + nPos + nBlockLength ) <= nLength )
 							{
                                 // read always in UTF8, some tools seem not to set UTF8 bit
@@ -926,7 +1110,7 @@ sal_Int32 ZipFile::recover()
 									aEntry.nPathLen = static_cast< sal_Int16 >(aFileName.getLength());
 								}
 
-								aEntry.nOffset = nGenPos + nPos + 30 + aEntry.nPathLen + aEntry.nExtraLen;
+								aEntry.nFileDataOffset = nGenPos + nPos + 30 + aEntry.nPathLen + aEntry.nLOCExtraLen;
 
 								if ( ( aEntry.nSize || aEntry.nCompressedSize ) && !checkSizeAndCRC( aEntry ) )
 								{
@@ -944,7 +1128,7 @@ sal_Int32 ZipFile::recover()
 					nPos += 4;
 				}
 				else if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 7 && pBuffer[nPos+3] == 8 )
-				{
+				{ // This is a data descriptor
 					sal_Int32 nCompressedSize, nSize, nCRC32;
 					MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 12 ) );
 					aMemGrabber >> nCRC32;
@@ -959,7 +1143,7 @@ sal_Int32 ZipFile::recover()
 						if( (*aIter).second.nFlag & 8 )
 						{
 							sal_Int32 nStreamOffset = nGenPos + nPos - nCompressedSize;
-							if ( nStreamOffset == (*aIter).second.nOffset && nCompressedSize > (*aIter).second.nCompressedSize )
+							if ( nStreamOffset == (*aIter).second.nFileDataOffset && nCompressedSize > (*aIter).second.nCompressedSize )
 							{
                                 // only DEFLATED blocks need to be checked
                                 sal_Bool bAcceptBlock = ( (*aIter).second.nMethod == STORED && nCompressedSize == nSize );
@@ -983,8 +1167,8 @@ sal_Int32 ZipFile::recover()
 							else if( !(*aIter).second.nCompressedSize )
 							{
 								(*aIter).second.nCrc = nCRC32;
-								sal_Int32 nRealStreamSize = nGenPos + nPos - (*aIter).second.nOffset;
-								(*aIter).second.nCompressedSize = nGenPos + nPos - (*aIter).second.nOffset;
+								sal_Int32 nRealStreamSize = nGenPos + nPos - (*aIter).second.nFileDataOffset;
+								(*aIter).second.nCompressedSize = nGenPos + nPos - (*aIter).second.nFileDataOffset;
 								(*aIter).second.nSize = nSize;
 							}
 #endif
@@ -1024,13 +1208,13 @@ sal_Bool ZipFile::checkSizeAndCRC( const ZipEntry& aEntry )
 	sal_Int32 nSize = 0, nCRC = 0;
 
 	if( aEntry.nMethod == STORED )
-		return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc );
+		return ( getCRC( aEntry.nFileDataOffset, aEntry.nSize ) == aEntry.nCrc );
 
-	getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC );
+	getSizeAndCRC( aEntry.nFileDataOffset, aEntry.nCompressedSize, &nSize, &nCRC );
 	return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC );
 }
 
-sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize )
+sal_Int32 ZipFile::getCRC( sal_Int32 nFileDataOffset, sal_Int32 nSize )
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
@@ -1038,7 +1222,7 @@ sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize )
 	CRC32 aCRC;
 	sal_Int32 nBlockSize = ::std::min( nSize, static_cast< sal_Int32 >( 32000 ) );
 
-	aGrabber.seek( nOffset );
+	aGrabber.seek( nFileDataOffset );
 	for ( int ind = 0;
 		  aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize;
 		  ind++ )
@@ -1049,7 +1233,7 @@ sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize )
 	return aCRC.getValue();
 }
 
-void ZipFile::getSizeAndCRC( sal_Int32 nOffset, sal_Int32 nCompressedSize, sal_Int32 *nSize, sal_Int32 *nCRC )
+void ZipFile::getSizeAndCRC( sal_Int32 nFileDataOffset, sal_Int32 nCompressedSize, sal_Int32 *nSize, sal_Int32 *nCRC )
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
@@ -1059,7 +1243,7 @@ void ZipFile::getSizeAndCRC( sal_Int32 nOffset, sal_Int32 nCompressedSize, sal_I
 	Inflater aInflaterLocal( sal_True );
 	sal_Int32 nBlockSize = ::std::min( nCompressedSize, static_cast< sal_Int32 >( 32000 ) );
 
-	aGrabber.seek( nOffset );
+	aGrabber.seek( nFileDataOffset );
 	for ( int ind = 0;
 		  !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize;
 		  ind++ )
diff --git a/main/package/source/package/zipapi/ZipOutputStream.cxx b/main/package/source/package/zipapi/ZipOutputStream.cxx
index ea1bbfc64e..9cbc68e418 100644
--- a/main/package/source/package/zipapi/ZipOutputStream.cxx
+++ b/main/package/source/package/zipapi/ZipOutputStream.cxx
@@ -110,7 +110,7 @@ void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry,
 		m_pCurrentStream = pStream;
 	}
 	sal_Int32 nLOCLength = writeLOC(rEntry);
-	rEntry.nOffset = static_cast < sal_Int32 > (aChucker.GetPosition()) - nLOCLength;
+	rEntry.nFileHeaderOffset = static_cast < sal_Int32 > (aChucker.GetPosition()) - nLOCLength;
 	aZipList.push_back( &rEntry );
 	pCurrentEntry = &rEntry;
 }
@@ -239,10 +239,10 @@ void SAL_CALL ZipOutputStream::finish(  )
 	if (aZipList.size() < 1)
 		OSL_ENSURE(false,"Zip file must have at least one entry!\n");
 
-	sal_Int32 nOffset= static_cast < sal_Int32 > (aChucker.GetPosition());
+	sal_Int32 nCENOffset= static_cast < sal_Int32 > (aChucker.GetPosition());
 	for (sal_Int32 i =0, nEnd = aZipList.size(); i < nEnd; i++)
 		writeCEN( *aZipList[i] );
-	writeEND( nOffset, static_cast < sal_Int32 > (aChucker.GetPosition()) - nOffset);
+	writeEND( nCENOffset, static_cast < sal_Int32 > (aChucker.GetPosition()) - nCENOffset);
 	bFinished = sal_True;
 	xStream->flush();
 }
@@ -296,7 +296,7 @@ void ZipOutputStream::doDeflate()
     }
 }
 
-void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
+void ZipOutputStream::writeEND(sal_uInt32 nCENOffset, sal_uInt32 nLength)
 	throw(IOException, RuntimeException)
 {
 	aChucker << ENDSIG;
@@ -305,7 +305,7 @@ void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
 	aChucker << static_cast < sal_Int16 > ( aZipList.size() );
 	aChucker << static_cast < sal_Int16 > ( aZipList.size() );
 	aChucker << nLength;
-	aChucker << nOffset;
+	aChucker << nCENOffset;
 	aChucker << static_cast < sal_Int16 > ( 0 );
 }
 void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
@@ -338,12 +338,12 @@ void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
 	aChucker << rEntry.nCompressedSize;
 	aChucker << rEntry.nSize;
 	aChucker << nNameLength;
-	aChucker << static_cast < sal_Int16> (0);
-	aChucker << static_cast < sal_Int16> (0);
-	aChucker << static_cast < sal_Int16> (0);
-	aChucker << static_cast < sal_Int16> (0);
-	aChucker << static_cast < sal_Int32> (0);
-	aChucker << rEntry.nOffset;
+	aChucker << static_cast < sal_Int16> (0); // extra field length
+	aChucker << static_cast < sal_Int16> (0); // file comment length
+	aChucker << static_cast < sal_Int16> (0); // disk number start
+	aChucker << static_cast < sal_Int16> (0); // internal file attributes
+	aChucker << static_cast < sal_Int32> (0); // external file attributes
+	aChucker << rEntry.nFileHeaderOffset;
 
 	Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
 	aChucker.WriteBytes( aSequence );
@@ -367,40 +367,40 @@ sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
 	sal_Int16 nNameLength 		= static_cast < sal_Int16 > ( sUTF8Name.getLength() );
 
 	aChucker << LOCSIG;
-	aChucker << rEntry.nVersion;
+	aChucker << rEntry.nVersion; // version needed to extract
 
 	if (rEntry.nFlag & (1 << 4) )
 	{
 		// If it's an encrypted entry, we pretend its stored plain text
 		sal_Int16 nTmpFlag = rEntry.nFlag;
 		nTmpFlag &= ~(1 <<4 );
-		aChucker << nTmpFlag;
-		aChucker << static_cast < sal_Int16 > ( STORED );
+		aChucker << nTmpFlag;	// general purpose bit flag
+		aChucker << static_cast < sal_Int16 > ( STORED ); // compression method
 	}
 	else
 	{
-		aChucker << rEntry.nFlag;
-		aChucker << rEntry.nMethod;
+		aChucker << rEntry.nFlag; // general purpose bit flag
+		aChucker << rEntry.nMethod; // compression method
 	}
 
-	aChucker << static_cast < sal_uInt32 > (rEntry.nTime);
+	aChucker << static_cast < sal_uInt32 > (rEntry.nTime); // last mod file time & date
 	if ((rEntry.nFlag & 8) == 8 )
 	{
-		aChucker << static_cast < sal_Int32 > (0);
-		aChucker << static_cast < sal_Int32 > (0);
-		aChucker << static_cast < sal_Int32 > (0);
+		aChucker << static_cast < sal_Int32 > (0); // crc-32
+		aChucker << static_cast < sal_Int32 > (0); // compressed size
+		aChucker << static_cast < sal_Int32 > (0); // uncompressed size
 	}
 	else
 	{
-		aChucker << static_cast < sal_uInt32 > (rEntry.nCrc);
-		aChucker << rEntry.nCompressedSize;
-		aChucker << rEntry.nSize;
+		aChucker << static_cast < sal_uInt32 > (rEntry.nCrc); // crc-32
+		aChucker << rEntry.nCompressedSize; // compressed size
+		aChucker << rEntry.nSize; // uncompressed size
 	}
-	aChucker << nNameLength;
-	aChucker << static_cast < sal_Int16 > (0);
+	aChucker << nNameLength; // file name length
+	aChucker << static_cast < sal_Int16 > (0); // extra field length
 
 	Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
-	aChucker.WriteBytes( aSequence );
+	aChucker.WriteBytes( aSequence ); // file name
 
 	return LOCHDR + nNameLength;
 }
diff --git a/main/package/source/package/zippackage/ZipPackage.cxx b/main/package/source/package/zippackage/ZipPackage.cxx
index 9885debfdf..3a4da44702 100644
--- a/main/package/source/package/zippackage/ZipPackage.cxx
+++ b/main/package/source/package/zippackage/ZipPackage.cxx
@@ -536,6 +536,7 @@ void ZipPackage::getZipFileContents()
 	OUString sTemp, sDirName;
 	sal_Int32 nOldIndex, nIndex, nStreamIndex;
 	FolderHash::iterator aIter;
+	sal_Bool mustHaveEncryption = sal_False;
 
 	while ( pEnum->hasMoreElements() )
 	{
@@ -591,12 +592,16 @@ void ZipPackage::getZipFileContents()
 			pPkgStream->setName( sTemp );
 			pPkgStream->doSetParent( pCurrent, sal_True );
 		}
+		if ( ( rEntry.nMethod == STORED ) && rEntry.bHasDataDescriptor )
+			mustHaveEncryption = sal_True;
 	}
 
 	if ( m_nFormat == embed::StorageFormats::PACKAGE )
 		parseManifest();
 	else if ( m_nFormat == embed::StorageFormats::OFOPXML )
 		parseContentType();
+	if ( mustHaveEncryption && !m_bHasEncryptedEntries )
+		throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "inconsistent ZIP entries" ) ), uno::Reference < XInterface > () );
 }
 
 //--------------------------------------------------------
diff --git a/main/package/source/package/zippackage/ZipPackageFolder.cxx b/main/package/source/package/zippackage/ZipPackageFolder.cxx
index 71f8552788..fc8deecfe5 100644
--- a/main/package/source/package/zippackage/ZipPackageFolder.cxx
+++ b/main/package/source/package/zippackage/ZipPackageFolder.cxx
@@ -75,7 +75,9 @@ ZipPackageFolder::ZipPackageFolder ( const uno::Reference< XMultiServiceFactory
 	aEntry.nCrc			= 0;
 	aEntry.nCompressedSize	= 0;
 	aEntry.nSize		= 0;
-	aEntry.nOffset		= -1;
+	aEntry.nFileHeaderOffset		= -1;
+	aEntry.nFileDataOffset		= -1;
+	aEntry.bHasDataDescriptor = sal_False;
 	uno::Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
 	if ( !rCachedImplId.getLength() )
 	    rCachedImplId = getImplementationId();
@@ -176,10 +178,13 @@ void ZipPackageFolder::copyZipEntry( ZipEntry &rDest, const ZipEntry &rSource)
     rDest.nCrc				= rSource.nCrc;
     rDest.nCompressedSize	= rSource.nCompressedSize;
     rDest.nSize				= rSource.nSize;
-    rDest.nOffset			= rSource.nOffset;
+    rDest.nFileHeaderOffset	= rSource.nFileHeaderOffset;
+	rDest.nFileDataOffset	= rSource.nFileDataOffset;
     rDest.sPath				= rSource.sPath;
     rDest.nPathLen			= rSource.nPathLen;
-    rDest.nExtraLen			= rSource.nExtraLen;
+    rDest.nLOCExtraLen		= rSource.nLOCExtraLen;
+	rDest.nCENExtraLen		= rSource.nCENExtraLen;
+	rDest.bHasDataDescriptor= rSource.bHasDataDescriptor;
 }
 
 const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageFolder::static_getImplementationId()
@@ -669,7 +674,7 @@ bool ZipPackageFolder::saveChild( const ::rtl::OUString &rShortName, const Conte
             if ( rInfo.pStream->IsEncrypted() )
                 rInfo.pStream->setSize( nOwnStreamOrigSize );
 
-            rInfo.pStream->aEntry.nOffset *= -1;
+            rInfo.pStream->aEntry.nFileDataOffset = rInfo.pStream->aEntry.nFileHeaderOffset;
         }
     }
 
@@ -692,7 +697,7 @@ void ZipPackageFolder::saveContents( ::rtl::OUString &rPath, std::vector < uno::
 		ZipEntry* pTempEntry = new ZipEntry();
 		ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry );
 		pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getLength() );
-		pTempEntry->nExtraLen = -1;
+		pTempEntry->nLOCExtraLen = -1;
 		pTempEntry->sPath = rPath;
 
 		try
diff --git a/main/package/source/package/zippackage/ZipPackageStream.cxx b/main/package/source/package/zippackage/ZipPackageStream.cxx
index 7cb6caff72..3bfa7bd7bb 100644
--- a/main/package/source/package/zippackage/ZipPackageStream.cxx
+++ b/main/package/source/package/zippackage/ZipPackageStream.cxx
@@ -96,9 +96,12 @@ ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
 	aEntry.nCrc			= -1;
 	aEntry.nCompressedSize	= -1;
 	aEntry.nSize		= -1;
-	aEntry.nOffset		= -1;
+	aEntry.nFileHeaderOffset		= -1;
+	aEntry.nFileDataOffset		= -1;
 	aEntry.nPathLen		= -1;
-	aEntry.nExtraLen	= -1;
+	aEntry.nLOCExtraLen	= -1;
+	aEntry.nCENExtraLen	= -1;
+	aEntry.bHasDataDescriptor = sal_False;
 
 	Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
 	if ( !rCachedImplId.getLength() )
@@ -118,10 +121,13 @@ void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
 	aEntry.nCrc = rInEntry.nCrc;
 	aEntry.nCompressedSize = rInEntry.nCompressedSize;
 	aEntry.nSize = rInEntry.nSize;
-	aEntry.nOffset = rInEntry.nOffset;
+	aEntry.nFileHeaderOffset = rInEntry.nFileHeaderOffset;
+	aEntry.nFileDataOffset = rInEntry.nFileDataOffset;
 	aEntry.sPath = rInEntry.sPath;
 	aEntry.nPathLen = rInEntry.nPathLen;
-	aEntry.nExtraLen = rInEntry.nExtraLen;
+	aEntry.nLOCExtraLen = rInEntry.nLOCExtraLen;
+	aEntry.nCENExtraLen = rInEntry.nCENExtraLen;
+	aEntry.bHasDataDescriptor = rInEntry.bHasDataDescriptor;
 
 	if ( aEntry.nMethod == STORED )
 		bToBeCompressed = sal_False;