https://bugs.documentfoundation.org/show_bug.cgi?id=174172
Bug ID: 174172
Summary: FILEOPEN: valid non-Zip64 package > 2 GiB reported as
corrupt (central directory offset read as signed
32-bit)
Product: LibreOffice
Version: 26.8.1.1 release
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: medium
Component: filters and storage
Assignee: [email protected]
Reporter: [email protected]
Description:
A valid ZIP package (PPTX or ODP) whose total size is above 2 GiB but below
4 GiB, and which does not use Zip64, cannot be opened. LibreOffice shows
"The file '...' is corrupt and therefore cannot be opened. LibreOffice can try
to repair the file." In headless mode, --convert-to fails with
"Error: source file could not be loaded".
I hit this with a real 2.9 GiB PPTX saved by PowerPoint (8 embedded MP4
videos, the largest 1.87 GB). Python's zipfile validates it without errors
(all CRCs OK, no Zip64 records or extra fields). Its End of
Central Directory record has central directory offset = 3,108,777,763. That is
a legal value for a classic (non-Zip64) ZIP, because the field is an unsigned
32-bit value, so Zip64 is not required below 4 GiB.
The threshold is exactly 2^31 bytes, and it does not depend on the format:
file size (bytes) PPTX ODP
1,992,29x,xxx opens opens
2,139,09x,xxx opens opens
2,155,86x,xxx FAILS FAILS
2,306,86x,xxx FAILS FAILS
Likely cause, in package/source/zipapi/ZipFile.cxx,
ZipFile::findCentralDirectory():
sal_Int32 const nEndDirSize = aGrabber.ReadInt32();
sal_Int32 const nEndDirOffset = aGrabber.ReadInt32();
...
if (o3tl::checked_add<sal_Int32>(nEndDirOffset, nEndDirSize, end)
|| nEndPos < end
|| nEndDirOffset < 0
...
throw ZipException(u"Invalid END header (bad central directory
size)"_ustr);
https://github.com/LibreOffice/core/blob/924fec653c3e6a52e2a6341d987ca7b031a612e4/package/source/zipapi/ZipFile.cxx#L1203-L1308
The EOCD "offset of start of central directory" and "size of central
directory" fields are unsigned 32-bit values (APPNOTE 4.4.23/4.4.24). They are
read as sal_Int32, so any offset >= 2^31 becomes negative and the package is
rejected. readCEN() also keeps the position in a sal_Int32 nCenPos. The
per-entry "relative offset of local header" field (APPNOTE 4.4.16) is
probably affected in the same way. Reading these fields as sal_uInt32 and
widening them to sal_Int64 should fix it.
Steps to Reproduce:
1. Download the attached make_large_package.py and hello.pptx (a 1-slide
presentation).
2. python3 make_large_package.py hello.pptx big.pptx 2200
This creates a ~2.2 GiB valid, non-Zip64 PPTX. It contains every entry of
hello.pptx plus unreferenced, stored 1 GiB padding entries. All entries
are < 2 GiB, and all header and EOCD fields are < 4 GiB.
3. Open big.pptx in Impress (or run:
soffice --headless --convert-to pdf big.pptx).
The same works with an ODP input. The script also adds the padding entries to
META-INF/manifest.xml.
Actual Results:
"The file 'big.pptx' is corrupt and therefore cannot be opened..." / headless:
"Error: source file could not be loaded".
With size 2040 instead of 2200 (just under 2^31 bytes), the file opens
normally.
Expected Results:
The file opens. A non-Zip64 ZIP is valid up to 4 GiB.
Reproducible: Always
User Profile Reset: Yes (tested with a fresh -env:UserInstallation profile)
Additional Info:
Related, but not the same bug:
- tdf#168495 Writer will not save a large (>2GB) document (FILESAVE)
- tdf#165762 Error saving a huge file (content.xml unpacked size > 4 GB)
(FILESAVE, Zip64)
- tdf#128244 / tdf#82984 Zip64 reading (FIXED). These cover packages that
use Zip64, not packages between 2 and 4 GiB that are valid without it.
Version: 26.8.1.1 (bf6ef2662401c7d6dce671ab4deb26ee0af3a7c1)
OS: macOS 27.0.1, arm64 (all tests above).
I first noticed the problem on Linux, where large PPTX files failed to open
with the same "corrupt" dialog. The code path is platform-independent, so all
platforms are affected.
--
You are receiving this mail because:
You are the assignee for the bug.