Skip to content

Fix Zip64 archive central directory extraction in ZipReader - #30685

Open
meteorcloudy wants to merge 1 commit into
bazelbuild:masterfrom
meteorcloudy:fix-zip64-extraction
Open

Fix Zip64 archive central directory extraction in ZipReader#30685
meteorcloudy wants to merge 1 commit into
bazelbuild:masterfrom
meteorcloudy:fix-zip64-extraction

Conversation

@meteorcloudy

Copy link
Copy Markdown
Member

Description

Fixes #30681.

In commit b12c06a (#30530), ZipReader.readCentralDirectory() was modified to compute the central directory start as actualCenStart = actualCenEnd - zipData.getCentralDirectorySize(), replacing the parsed zipData.getCentralDirectoryOffset().

This broke reading standard Zip64 archives where 32-bit EOCD fields do not overflow (as the 76-byte Zip64 EOCD and locator sit between the central directory and the 32-bit EOCD, shifting the computed offset 76 bytes into the central directory) or when centralDirectorySize is 0xFFFFFFFF.

This change:

  1. Restores ZipReader's standard central directory parsing to use zipData.getCentralDirectoryOffset().
  2. Populates centralDirectorySize in Zip64EndOfCentralDirectory.read().
  3. Restricts the unadjusted SFX central directory start computation strictly to AdjustSfx.
  4. Adds a unit test in ZipReaderTest covering Zip64 archives with valid 32-bit EOCD offsets.

In commit b12c06a, ZipReader.readCentralDirectory() was modified to compute the central directory offset as actualCenEnd - zipData.getCentralDirectorySize(), replacing the parsed zipData.getCentralDirectoryOffset().

This broke reading standard Zip64 archives where 32-bit EOCD fields do not overflow (as the 76-byte Zip64 EOCD and locator sit between the central directory and the 32-bit EOCD, shifting the computed offset 76 bytes into the central directory) or when centralDirectorySize is 0xFFFFFFFF.

This change restores ZipReader's standard central directory parsing to use zipData.getCentralDirectoryOffset(), populates centralDirectorySize in Zip64EndOfCentralDirectory.read(), and restricts the unadjusted SFX calculation strictly to AdjustSfx.

Fixes bazelbuild#30681.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression in ZipReader central directory parsing for Zip64 archives introduced by #30530 / issue #30681, restoring correct central directory start handling while isolating SFX-specific offset heuristics to AdjustSfx.

Changes:

  • Reverts Zip64 central directory start computation to use the parsed central directory offset (and narrows “end-minus-size” computation to SFX adjustment only).
  • Populates centralDirectorySize from the Zip64 EOCD record to support correct size-based computations.
  • Adds a regression test for Zip64 archives that include Zip64 EOCD/locator while still having valid 32-bit EOCD offsets; updates SFX-related test and tool usage to use the new AdjustSfx-specific reader construction.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/java_tools/singlejar/javatests/com/google/devtools/build/zip/ZipReaderTest.java Adds a Zip64 regression test and updates SFX test to use the AdjustSfx-specific ZipReader creation path.
src/java_tools/singlejar/java/com/google/devtools/build/zip/ZipReader.java Restores standard central directory parsing behavior and introduces an AdjustSfx-only parsing mode.
src/java_tools/singlejar/java/com/google/devtools/build/zip/Zip64EndOfCentralDirectory.java Ensures Zip64 EOCD parsing populates central directory size.
src/java_tools/singlejar/java/com/google/devtools/build/zip/AdjustSfx.java Switches AdjustSfx to use the AdjustSfx-specific ZipReader creation path.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +224 to +228
if (isUnadjustedSfx) {
long actualCenEnd =
(zipData.isZip64() && zipData.getZip64EndOfCentralDirectoryOffset() > 0)
? zipData.getZip64EndOfCentralDirectoryOffset()
: eocdLocation;
@bazel-docs-pr-commenter

Copy link
Copy Markdown

✅ Bazel docs preview is ready!

Preview URL: https://bazel-pr-30685.mintlify.app/

Updated for 7762eba9733e9c6ba3e5d88d98aa0e1024988c1b

@ted-xie ted-xie left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! There have been a few problems reported with the AdjustSfx and modified singlejar logic so I think all of that may need some re-architecting in the near future.

@Test
public void testZip64_WithZip32Offsets() throws IOException {
// A zip file with Zip64 EOCD and Locator, but with non-overflowing 32-bit values in EOCD (as generated by Python / standard tools for archives with Zip64 entries).
byte[] data = new byte[] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This huge array will be unpleasant to maintain, but it's fine for now.

@ted-xie ted-xie added team-OSS Issues for the Bazel OSS team: installation, release processBazel packaging, website awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally and removed team-Rules-Java Issues for Java rules awaiting-review PR is awaiting review from an assigned reviewer labels Aug 12, 2026
@ted-xie

ted-xie commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@bazel-io fork 8.8.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally team-OSS Issues for the Bazel OSS team: installation, release processBazel packaging, website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Zip64 archive extraction broken in 8.8.0rc1: "Malformed Central Directory File Header" (regression from #30530)

3 participants