diff --git a/src/java.base/share/classes/java/util/zip/ZipEntry.java b/src/java.base/share/classes/java/util/zip/ZipEntry.java index 243779a7c49..b7ecd1bea8f 100644 --- a/src/java.base/share/classes/java/util/zip/ZipEntry.java +++ b/src/java.base/share/classes/java/util/zip/ZipEntry.java @@ -564,20 +564,20 @@ public class ZipEntry implements ZipConstants, Cloneable { // be the magic value and it "accidentally" has some // bytes in extra match the id. if (sz >= 16) { - size = get64(extra, off); - csize = get64(extra, off + 8); + size = get64S(extra, off); + csize = get64S(extra, off + 8); } } else { // CEN extra zip64 if (size == ZIP64_MAGICVAL) { if (off + 8 > len) // invalid zip64 extra break; // fields, just skip - size = get64(extra, off); + size = get64S(extra, off); } if (csize == ZIP64_MAGICVAL) { if (off + 16 > len) // invalid zip64 extra break; // fields, just skip - csize = get64(extra, off + 8); + csize = get64S(extra, off + 8); } } } @@ -588,15 +588,15 @@ public class ZipEntry implements ZipConstants, Cloneable { int pos = off + 4; // reserved 4 bytes if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24) break; - long wtime = get64(extra, pos + 4); + long wtime = get64S(extra, pos + 4); if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { mtime = winTimeToFileTime(wtime); } - wtime = get64(extra, pos + 12); + wtime = get64S(extra, pos + 12); if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { atime = winTimeToFileTime(wtime); } - wtime = get64(extra, pos + 20); + wtime = get64S(extra, pos + 20); if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { ctime = winTimeToFileTime(wtime); } diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index a6b6dce1a14..17256f71929 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -906,21 +906,21 @@ public class ZipFile implements ZipConstants, Closeable { if (size == ZIP64_MAGICVAL) { if (sz < 8 || (off + 8) > end) break; - size = get64(cen, off); + size = get64S(cen, off); sz -= 8; off += 8; } if (rem == ZIP64_MAGICVAL) { if (sz < 8 || (off + 8) > end) break; - rem = get64(cen, off); + rem = get64S(cen, off); sz -= 8; off += 8; } if (pos == ZIP64_MAGICVAL) { if (sz < 8 || (off + 8) > end) break; - pos = get64(cen, off); + pos = get64S(cen, off); sz -= 8; off += 8; } @@ -1376,7 +1376,7 @@ public class ZipFile implements ZipConstants, Closeable { // Check the uncompressed size is not negative if (size == ZIP64_MAGICVAL) { if ( blockSize >= Long.BYTES) { - if (get64(cen, off) < 0) { + if (get64S(cen, off) < 0) { zerror("Invalid zip64 extra block size value"); } off += Long.BYTES; @@ -1388,7 +1388,7 @@ public class ZipFile implements ZipConstants, Closeable { // Check the compressed size is not negative if (csize == ZIP64_MAGICVAL) { if (blockSize >= Long.BYTES) { - if (get64(cen, off) < 0) { + if (get64S(cen, off) < 0) { zerror("Invalid zip64 extra block compressed size value"); } off += Long.BYTES; @@ -1400,7 +1400,7 @@ public class ZipFile implements ZipConstants, Closeable { // Check the LOC offset is not negative if (locoff == ZIP64_MAGICVAL) { if (blockSize >= Long.BYTES) { - if (get64(cen, off) < 0) { + if (get64S(cen, off) < 0) { zerror("Invalid zip64 extra block LOC OFFSET value"); } // Note: We do not need to adjust the following fields as @@ -1641,10 +1641,7 @@ public class ZipFile implements ZipConstants, Closeable { } // Now scan the block backwards for END header signature for (int i = buf.length - ENDHDR; i >= 0; i--) { - if (buf[i+0] == (byte)'P' && - buf[i+1] == (byte)'K' && - buf[i+2] == (byte)'\005' && - buf[i+3] == (byte)'\006') { + if (get32(buf, i) == ENDSIG) { // Found ENDSIG header byte[] endbuf = Arrays.copyOfRange(buf, i, i + ENDHDR); end.centot = ENDTOT(endbuf); @@ -1664,9 +1661,9 @@ public class ZipFile implements ZipConstants, Closeable { if (cenpos < 0 || locpos < 0 || readFullyAt(sbuf, 0, sbuf.length, cenpos) != 4 || - GETSIG(sbuf) != CENSIG || + get32(sbuf, 0) != CENSIG || readFullyAt(sbuf, 0, sbuf.length, locpos) != 4 || - GETSIG(sbuf) != LOCSIG) { + get32(sbuf, 0) != LOCSIG) { continue; } } @@ -1681,13 +1678,13 @@ public class ZipFile implements ZipConstants, Closeable { byte[] loc64 = new byte[ZIP64_LOCHDR]; if (end.endpos < ZIP64_LOCHDR || readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR) - != loc64.length || GETSIG(loc64) != ZIP64_LOCSIG) { + != loc64.length || get32(loc64, 0) != ZIP64_LOCSIG) { return end; } long end64pos = ZIP64_LOCOFF(loc64); byte[] end64buf = new byte[ZIP64_ENDHDR]; if (readFullyAt(end64buf, 0, end64buf.length, end64pos) - != end64buf.length || GETSIG(end64buf) != ZIP64_ENDSIG) { + != end64buf.length || get32(end64buf, 0) != ZIP64_ENDSIG) { return end; } // end64 candidate found, diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java index 5302cf75160..3a433cf5c6d 100644 --- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java @@ -603,14 +603,14 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants long sig = get32(tmpbuf, 0); if (sig != EXTSIG) { // no EXTSIG present e.crc = sig; - e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); - e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); + e.csize = get64S(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); + e.size = get64S(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); ((PushbackInputStream)in).unread( tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC); } else { e.crc = get32(tmpbuf, ZIP64_EXTCRC); - e.csize = get64(tmpbuf, ZIP64_EXTSIZ); - e.size = get64(tmpbuf, ZIP64_EXTLEN); + e.csize = get64S(tmpbuf, ZIP64_EXTSIZ); + e.size = get64S(tmpbuf, ZIP64_EXTLEN); } } else { readFully(tmpbuf, 0, EXTHDR); diff --git a/src/java.base/share/classes/java/util/zip/ZipUtils.java b/src/java.base/share/classes/java/util/zip/ZipUtils.java index ab37fc03a56..5b1d896f420 100644 --- a/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -39,6 +39,7 @@ import static java.util.zip.ZipConstants.ENDHDR; import jdk.internal.access.JavaNioAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; +import jdk.internal.util.Preconditions; class ZipUtils { @@ -170,7 +171,10 @@ class ZipUtils { * The bytes are assumed to be in Intel (little-endian) byte order. */ public static final int get16(byte[] b, int off) { - return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); + Preconditions.checkIndex(off, b.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(off + 1, b.length, Preconditions.AIOOBE_FORMATTER); + return Short.toUnsignedInt( + UNSAFE.getShortUnaligned(b, off + Unsafe.ARRAY_BYTE_BASE_OFFSET, false)); } /** @@ -178,15 +182,20 @@ class ZipUtils { * The bytes are assumed to be in Intel (little-endian) byte order. */ public static final long get32(byte[] b, int off) { - return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL; + Preconditions.checkIndex(off, b.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(off + 3, b.length, Preconditions.AIOOBE_FORMATTER); + return Integer.toUnsignedLong( + UNSAFE.getIntUnaligned(b, off + Unsafe.ARRAY_BYTE_BASE_OFFSET, false)); } /** * Fetches signed 64-bit value from byte array at specified offset. * The bytes are assumed to be in Intel (little-endian) byte order. */ - public static final long get64(byte[] b, int off) { - return get32(b, off) | (get32(b, off+4) << 32); + public static final long get64S(byte[] b, int off) { + Preconditions.checkIndex(off, b.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(off + 7, b.length, Preconditions.AIOOBE_FORMATTER); + return UNSAFE.getLongUnaligned(b, off + Unsafe.ARRAY_BYTE_BASE_OFFSET, false); } /** @@ -195,28 +204,9 @@ class ZipUtils { * */ public static final int get32S(byte[] b, int off) { - return (get16(b, off) | (get16(b, off+2) << 16)); - } - - // fields access methods - static final int CH(byte[] b, int n) { - return b[n] & 0xff ; - } - - static final int SH(byte[] b, int n) { - return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8); - } - - static final long LG(byte[] b, int n) { - return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL; - } - - static final long LL(byte[] b, int n) { - return (LG(b, n)) | (LG(b, n + 4) << 32); - } - - static final long GETSIG(byte[] b) { - return LG(b, 0); + Preconditions.checkIndex(off, b.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(off + 3, b.length, Preconditions.AIOOBE_FORMATTER); + return UNSAFE.getIntUnaligned(b, off + Unsafe.ARRAY_BYTE_BASE_OFFSET, false); } /* @@ -231,56 +221,56 @@ class ZipUtils { // local file (LOC) header fields - static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature - static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract - static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags - static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method - static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time - static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data - static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size - static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size - static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length - static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length + static final long LOCSIG(byte[] b) { return get32(b, 0); } // signature + static final int LOCVER(byte[] b) { return get16(b, 4); } // version needed to extract + static final int LOCFLG(byte[] b) { return get16(b, 6); } // general purpose bit flags + static final int LOCHOW(byte[] b) { return get16(b, 8); } // compression method + static final long LOCTIM(byte[] b) { return get32(b, 10);} // modification time + static final long LOCCRC(byte[] b) { return get32(b, 14);} // crc of uncompressed data + static final long LOCSIZ(byte[] b) { return get32(b, 18);} // compressed data size + static final long LOCLEN(byte[] b) { return get32(b, 22);} // uncompressed data size + static final int LOCNAM(byte[] b) { return get16(b, 26);} // filename length + static final int LOCEXT(byte[] b) { return get16(b, 28);} // extra field length // extra local (EXT) header fields - static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data - static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size - static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size + static final long EXTCRC(byte[] b) { return get32(b, 4);} // crc of uncompressed data + static final long EXTSIZ(byte[] b) { return get32(b, 8);} // compressed size + static final long EXTLEN(byte[] b) { return get32(b, 12);} // uncompressed size // end of central directory header (END) fields - static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk - static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries - static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size - static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset - static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of ZIP file comment - static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);} + static final int ENDSUB(byte[] b) { return get16(b, 8); } // number of entries on this disk + static final int ENDTOT(byte[] b) { return get16(b, 10);} // total number of entries + static final long ENDSIZ(byte[] b) { return get32(b, 12);} // central directory size + static final long ENDOFF(byte[] b) { return get32(b, 16);} // central directory offset + static final int ENDCOM(byte[] b) { return get16(b, 20);} // size of ZIP file comment + static final int ENDCOM(byte[] b, int off) { return get16(b, off + 20);} - // zip64 end of central directory recoder fields - static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk - static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries - static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size - static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset - static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset + // zip64 end of central directory record fields + static final long ZIP64_ENDTOD(byte[] b) { return get64S(b, 24);} // total number of entries on disk + static final long ZIP64_ENDTOT(byte[] b) { return get64S(b, 32);} // total number of entries + static final long ZIP64_ENDSIZ(byte[] b) { return get64S(b, 40);} // central directory size + static final long ZIP64_ENDOFF(byte[] b) { return get64S(b, 48);} // central directory offset + static final long ZIP64_LOCOFF(byte[] b) { return get64S(b, 8);} // zip64 end offset // central directory header (CEN) fields - static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } - static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } - static final int CENVEM_FA(byte[] b, int pos) { return CH(b, pos + 5); } // file attribute compatibility - static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } - static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } - static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} - static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);} - static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);} - static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);} - static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);} - static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);} - static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);} - static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);} - static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} - static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} - static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} - static final int CENATX_PERMS(byte[] b, int pos) { return SH(b, pos + 40);} // posix permission data - static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} + static final long CENSIG(byte[] b, int pos) { return get32(b, pos + 0); } + static final int CENVEM(byte[] b, int pos) { return get16(b, pos + 4); } + static final int CENVEM_FA(byte[] b, int pos) { return Byte.toUnsignedInt(b[pos + 5]); } // file attribute compatibility + static final int CENVER(byte[] b, int pos) { return get16(b, pos + 6); } + static final int CENFLG(byte[] b, int pos) { return get16(b, pos + 8); } + static final int CENHOW(byte[] b, int pos) { return get16(b, pos + 10);} + static final long CENTIM(byte[] b, int pos) { return get32(b, pos + 12);} + static final long CENCRC(byte[] b, int pos) { return get32(b, pos + 16);} + static final long CENSIZ(byte[] b, int pos) { return get32(b, pos + 20);} + static final long CENLEN(byte[] b, int pos) { return get32(b, pos + 24);} + static final int CENNAM(byte[] b, int pos) { return get16(b, pos + 28);} + static final int CENEXT(byte[] b, int pos) { return get16(b, pos + 30);} + static final int CENCOM(byte[] b, int pos) { return get16(b, pos + 32);} + static final int CENDSK(byte[] b, int pos) { return get16(b, pos + 34);} + static final int CENATT(byte[] b, int pos) { return get16(b, pos + 36);} + static final long CENATX(byte[] b, int pos) { return get32(b, pos + 38);} + static final int CENATX_PERMS(byte[] b, int pos) { return get16(b, pos + 40);} // posix permission data + static final long CENOFF(byte[] b, int pos) { return get32(b, pos + 42);} // The END header is followed by a variable length comment of size < 64k. static final long END_MAXLEN = 0xFFFF + ENDHDR; @@ -293,16 +283,16 @@ class ZipUtils { jdk.internal.loader.BootLoader.loadLibrary("zip"); } - private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb"); - private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset"); + private static final long byteBufferArrayOffset = UNSAFE.objectFieldOffset(ByteBuffer.class, "hb"); + private static final long byteBufferOffsetOffset = UNSAFE.objectFieldOffset(ByteBuffer.class, "offset"); static byte[] getBufferArray(ByteBuffer byteBuffer) { - return (byte[]) unsafe.getReference(byteBuffer, byteBufferArrayOffset); + return (byte[]) UNSAFE.getReference(byteBuffer, byteBufferArrayOffset); } static int getBufferOffset(ByteBuffer byteBuffer) { - return unsafe.getInt(byteBuffer, byteBufferOffsetOffset); + return UNSAFE.getInt(byteBuffer, byteBufferOffsetOffset); } } diff --git a/test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java b/test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java index e450fcfe9a0..4f6ae6373ec 100644 --- a/test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java +++ b/test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java @@ -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 @@ -107,4 +107,13 @@ public class ZipFileOpen { zf.close(); zf2.close(); } + + // Provide a simple one-off run without JMH dependencies enable simple debugging, + // diagnostics and dual-purposing this micro as a startup test. + public static void main(String... args) throws Exception { + var bench = new ZipFileOpen(); + bench.size = 1024*4; + bench.beforeRun(); + bench.openCloseZipFile(); + } }