8339711: ZipFile.Source.initCEN needlessly reads END header

Reviewed-by: lancea, jpai, redestad
This commit is contained in:
Eirik Bjørsnøs 2024-09-30 13:06:49 +00:00
parent 180affc571
commit cff420d8d3
3 changed files with 19 additions and 12 deletions

View File

@ -63,6 +63,7 @@ import java.util.stream.StreamSupport;
import jdk.internal.access.JavaUtilZipFileAccess;
import jdk.internal.access.JavaUtilJarAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ArraysSupport;
import jdk.internal.util.OperatingSystem;
import jdk.internal.perf.PerfCounter;
import jdk.internal.ref.CleanerFactory;
@ -1178,6 +1179,8 @@ public class ZipFile implements ZipConstants, Closeable {
// "META-INF/".length()
private static final int META_INF_LEN = 9;
private static final int[] EMPTY_META_VERSIONS = new int[0];
// CEN size is limited to the maximum array size in the JDK
private static final int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
private final Key key; // the key in files
private final @Stable ZipCoder zc; // ZIP coder used to decode/encode
@ -1185,7 +1188,7 @@ public class ZipFile implements ZipConstants, Closeable {
private int refs = 1;
private RandomAccessFile zfile; // zfile of the underlying ZIP file
private byte[] cen; // CEN & ENDHDR
private byte[] cen; // CEN
private long locpos; // position of first LOC header (usually 0)
private byte[] comment; // ZIP file comment
// list of meta entries in META-INF dir
@ -1241,7 +1244,7 @@ public class ZipFile implements ZipConstants, Closeable {
// should not exceed 65,535 bytes per the PKWare APP.NOTE
// 4.4.10, 4.4.11, & 4.4.12. Also check that current CEN header will
// not exceed the length of the CEN array
if (headerSize > 0xFFFF || pos + headerSize > cen.length - ENDHDR) {
if (headerSize > 0xFFFF || pos + headerSize > cen.length) {
zerror("invalid CEN header (bad header size)");
}
@ -1294,7 +1297,7 @@ public class ZipFile implements ZipConstants, Closeable {
}
// CEN Offset where this Extra field ends
int extraEndOffset = startingOffset + extraFieldLen;
if (extraEndOffset > cen.length - ENDHDR) {
if (extraEndOffset > cen.length) {
zerror("Invalid CEN header (extra data field size too long)");
}
int currentOffset = startingOffset;
@ -1732,12 +1735,12 @@ public class ZipFile implements ZipConstants, Closeable {
if (locpos < 0) {
zerror("invalid END header (bad central directory offset)");
}
// read in the CEN and END
if (end.cenlen + ENDHDR >= Integer.MAX_VALUE) {
// read in the CEN
if (end.cenlen > MAX_CEN_SIZE) {
zerror("invalid END header (central directory size too large)");
}
cen = this.cen = new byte[(int)(end.cenlen + ENDHDR)];
if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
cen = this.cen = new byte[(int)end.cenlen];
if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen) {
zerror("read CEN tables failed");
}
this.total = end.centot;
@ -1766,7 +1769,7 @@ public class ZipFile implements ZipConstants, Closeable {
int idx = 0; // Index into the entries array
int pos = 0;
int entryPos = CENHDR;
int limit = cen.length - ENDHDR;
int limit = cen.length;
manifestNum = 0;
while (entryPos <= limit) {
if (idx >= entriesLength) {
@ -1829,7 +1832,7 @@ public class ZipFile implements ZipConstants, Closeable {
} else {
metaVersions = EMPTY_META_VERSIONS;
}
if (pos + ENDHDR != cen.length) {
if (pos != cen.length) {
zerror("invalid CEN header (bad header size)");
}
}

View File

@ -23,10 +23,12 @@
/* @test
* @bug 8272746
* @modules java.base/jdk.internal.util
* @summary Verify that ZipFile rejects a ZIP with a CEN size which does not fit in a Java byte array
* @run junit CenSizeTooLarge
*/
import jdk.internal.util.ArraysSupport;
import org.junit.Before;
import org.junit.Test;
@ -49,7 +51,7 @@ public class CenSizeTooLarge {
public static final int NAME_LENGTH = 10;
// Maximum allowed CEN size allowed by the ZipFile implementation
static final int MAX_CEN_SIZE = Integer.MAX_VALUE - ZipFile.ENDHDR - 1;
static final int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/**
* From the APPNOTE.txt specification:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,10 +23,12 @@
/* @test
* @bug 8272746
* @modules java.base/jdk.internal.util
* @summary Verify that ZipFile rejects files with CEN sizes exceeding the implementation limit
* @run testng/othervm EndOfCenValidation
*/
import jdk.internal.util.ArraysSupport;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -68,7 +70,7 @@ public class EndOfCenValidation {
private static final int ENDSIZ = ZipFile.ENDSIZ; // Offset of CEN size field within ENDHDR
private static final int ENDOFF = ZipFile.ENDOFF; // Offset of CEN offset field within ENDHDR
// Maximum allowed CEN size allowed by ZipFile
private static int MAX_CEN_SIZE = Integer.MAX_VALUE - ENDHDR - 1;
private static int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
// Expected message when CEN size does not match file size
private static final String INVALID_CEN_BAD_SIZE = "invalid END header (bad central directory size)";