Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

archive/zip: potential bug with zip64 check #56249

Open
kleeon opened this issue Oct 15, 2022 · 3 comments
Open

archive/zip: potential bug with zip64 check #56249

kleeon opened this issue Oct 15, 2022 · 3 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@kleeon
Copy link

kleeon commented Oct 15, 2022

What version of Go are you using (go version)?

$ go version
go version go1.19.2 windows/amd64

There seems to be a bug with zip64 check on this line:

if d.directoryRecords == 0xffff || d.directorySize == 0xffff || d.directoryOffset == 0xffffffff {

Specifically the d.directorySize == 0xffff part. Size of central directory is a 32-bit value so it should be compared to 0xffffffff.

@dr2chase
Copy link
Contributor

@dsnet can you give this a look?

@dr2chase dr2chase added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 17, 2022
@dsnet
Copy link
Member

dsnet commented Oct 17, 2022

I'll take a look next week. This week is a bit busier.

@ZekeLu
Copy link
Contributor

ZekeLu commented Oct 17, 2022

According to section 4.4.23 of https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT:

4.4.23 size of the central directory: (4 bytes)

The size (in bytes) of the entire central directory.
If an archive is in ZIP64 format and the value in this field is 0xFFFFFFFF, the size will be in the corresponding 8 byte zip64 end of central directory field.

@kleeon is correct that it should compare with 0xFFFFFFFF.

The typo does not cause any issue because:

  1. if d.directorySize happens to be 0xffff, it will incorrectly call findDirectory64End. But findDirectory64End is guarded by directory64LocSignature so this is essentially a no-op.
  2. when d.directorySize is 0xffffffff, d.directoryOffset will be 0xffffffff too (more on this later). So findDirectory64End will be called anyway.

That said, the typo should be fixed anyway.

I used this code to generate a zip file that has a large size of the central directory. Both d.directorySize and d.directoryOffset are 0xffffffff. And the actual size are 0x10000D204 and 0x6DD198 respectively.

package main

import (
	"archive/zip"
	"fmt"
	"os"
	"strings"
)

func main() {
	// The file size will be 4.1G.
	archive, err := os.Create("z.zip")
	if err != nil {
		panic(err)
	}
	defer archive.Close()
	zipWriter := zip.NewWriter(archive)
	defer zipWriter.Close()

	comment := strings.Repeat("1", 64<<10-1)
	for i := 0; i < 65428; i++ {
		name := fmt.Sprintf("%060x.txt", i)
		h := &zip.FileHeader{
			Name:    name,
			Comment: comment,
		}
		_, err := zipWriter.CreateHeader(h)
		if err != nil {
			panic(err)
		}
	}
}

@seankhliao seankhliao added this to the Unplanned milestone Nov 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants