提交 9743e9f7 编写于 作者: P phh

8233234: Better Zip Naming

Reviewed-by: andrew, mbalao
Contributed-by: NJames Guo <junguoj@amazon.com>
上级 886efc87
/*
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, 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
......@@ -112,11 +112,11 @@ class ZipCoder {
return utf8.getBytes(s);
}
String toStringUTF8(byte[] ba, int len) {
static String toStringUTF8(byte[] ba, int len) {
return utf8.toString(ba, 0, len);
}
String toStringUTF8(byte[] ba, int off, int len) {
static String toStringUTF8(byte[] ba, int off, int len) {
return utf8.toString(ba, off, len);
}
......
/*
* Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2020, 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
......@@ -370,7 +370,7 @@ class ZipFile implements ZipConstants, Closeable {
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
Objects.requireNonNull(entry, "entry");
int pos = -1;
int pos;
ZipFileInputStream in;
Source zsrc = res.zsrc;
Set<InputStream> istreams = res.istreams;
......@@ -607,7 +607,7 @@ class ZipFile implements ZipConstants, Closeable {
byte[] cen = res.zsrc.cen;
int nlen = CENNAM(cen, pos);
if (!zc.isUTF8() && (CENFLG(cen, pos) & USE_UTF8) != 0) {
return zc.toStringUTF8(cen, pos + CENHDR, nlen);
return ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen);
} else {
return zc.toString(cen, pos + CENHDR, nlen);
}
......@@ -667,7 +667,7 @@ class ZipFile implements ZipConstants, Closeable {
// (2) not equal to the name stored, a slash is appended during
// getEntryPos() search.
if (!zc.isUTF8() && (flag & USE_UTF8) != 0) {
name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
name = ZipCoder.toStringUTF8(cen, pos + CENHDR, nlen);
} else {
name = zc.toString(cen, pos + CENHDR, nlen);
}
......@@ -686,7 +686,7 @@ class ZipFile implements ZipConstants, Closeable {
if (clen != 0) {
int start = pos + CENHDR + nlen + elen;
if (!zc.isUTF8() && (flag & USE_UTF8) != 0) {
e.comment = zc.toStringUTF8(cen, start, clen);
e.comment = ZipCoder.toStringUTF8(cen, start, clen);
} else {
e.comment = zc.toString(cen, start, clen);
}
......@@ -724,7 +724,7 @@ class ZipFile implements ZipConstants, Closeable {
this.cleanable = CleanerFactory.cleaner().register(zf, this);
this.istreams = Collections.newSetFromMap(new WeakHashMap<>());
this.inflaterCache = new ArrayDeque<>();
this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0, zf.zc);
}
void clean() {
......@@ -817,12 +817,12 @@ class ZipFile implements ZipConstants, Closeable {
}
}
CleanableResource(File file, int mode)
CleanableResource(File file, int mode, ZipCoder zc)
throws IOException {
this.cleanable = null;
this.istreams = Collections.newSetFromMap(new WeakHashMap<>());
this.inflaterCache = new ArrayDeque<>();
this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0, zc);
}
/*
......@@ -848,7 +848,7 @@ class ZipFile implements ZipConstants, Closeable {
ZipFile zf;
FinalizableResource(ZipFile zf, File file, int mode)
throws IOException {
super(file, mode);
super(file, mode, zf.zc);
this.zf = zf;
}
......@@ -1218,7 +1218,7 @@ class ZipFile implements ZipConstants, Closeable {
private static final HashMap<Key, Source> files = new HashMap<>();
static Source get(File file, boolean toDelete) throws IOException {
static Source get(File file, boolean toDelete, ZipCoder zc) throws IOException {
final Key key;
try {
key = new Key(file,
......@@ -1234,7 +1234,7 @@ class ZipFile implements ZipConstants, Closeable {
return src;
}
}
src = new Source(key, toDelete);
src = new Source(key, toDelete, zc);
synchronized (files) {
if (files.containsKey(key)) { // someone else put in first
......@@ -1257,7 +1257,7 @@ class ZipFile implements ZipConstants, Closeable {
}
}
private Source(Key key, boolean toDelete) throws IOException {
private Source(Key key, boolean toDelete, ZipCoder zc) throws IOException {
this.key = key;
if (toDelete) {
if (isWindows) {
......@@ -1271,7 +1271,7 @@ class ZipFile implements ZipConstants, Closeable {
this.zfile = new RandomAccessFile(key.file, "r");
}
try {
initCEN(-1);
initCEN(-1, zc);
byte[] buf = new byte[4];
readFullyAt(buf, 0, 4, 0);
this.startsWithLoc = (LOCSIG(buf) == LOCSIG);
......@@ -1318,6 +1318,32 @@ class ZipFile implements ZipConstants, Closeable {
}
}
private static final void checkUTF8(byte[] a, int pos, int len) throws ZipException {
try {
int end = pos + len;
while (pos < end) {
// ASCII fast-path: When checking that a range of bytes is
// valid UTF-8, we can avoid some allocation by skipping
// past bytes in the 0-127 range
if (a[pos] < 0) {
ZipCoder.toStringUTF8(a, pos, end - pos);
break;
}
pos++;
}
} catch(Exception e) {
zerror("invalid CEN header (bad entry name)");
}
}
private final void checkEncoding(ZipCoder zc, byte[] a, int pos, int nlen) throws ZipException {
try {
zc.toString(a, pos, nlen);
} catch(Exception e) {
zerror("invalid CEN header (bad entry name)");
}
}
private static final int hashN(byte[] a, int off, int len) {
int h = 1;
while (len-- > 0) {
......@@ -1438,7 +1464,7 @@ class ZipFile implements ZipConstants, Closeable {
}
// Reads zip file central directory.
private void initCEN(int knownTotal) throws IOException {
private void initCEN(int knownTotal, ZipCoder zc) throws IOException {
if (knownTotal == -1) {
End end = findEND();
if (end.endpos == 0) {
......@@ -1472,15 +1498,15 @@ class ZipFile implements ZipConstants, Closeable {
table = new int[tablelen];
Arrays.fill(table, ZIP_ENDCHAIN);
int idx = 0;
int hash = 0;
int next = -1;
int hash;
int next;
// list for all meta entries
ArrayList<Integer> metanamesList = null;
// Iterate through the entries in the central directory
int i = 0;
int hsh = 0;
int hsh;
int pos = 0;
int limit = cen.length - ENDHDR;
while (pos + CENHDR <= limit) {
......@@ -1488,7 +1514,7 @@ class ZipFile implements ZipConstants, Closeable {
// This will only happen if the zip file has an incorrect
// ENDTOT field, which usually means it contains more than
// 65535 entries.
initCEN(countCENHeaders(cen, limit));
initCEN(countCENHeaders(cen, limit), zc);
return;
}
if (CENSIG(cen, pos) != CENSIG)
......@@ -1497,12 +1523,18 @@ class ZipFile implements ZipConstants, Closeable {
int nlen = CENNAM(cen, pos);
int elen = CENEXT(cen, pos);
int clen = CENCOM(cen, pos);
if ((CENFLG(cen, pos) & 1) != 0)
int flag = CENFLG(cen, pos);
if ((flag & 1) != 0)
zerror("invalid CEN header (encrypted entry)");
if (method != STORED && method != DEFLATED)
zerror("invalid CEN header (bad compression method: " + method + ")");
if (pos + CENHDR + nlen > limit)
zerror("invalid CEN header (bad header size)");
if (zc.isUTF8() || (flag & USE_UTF8) != 0) {
checkUTF8(cen, pos + CENHDR, nlen);
} else {
checkEncoding(zc, cen, pos + CENHDR, nlen);
}
// Record the CEN offset and the name hash in our hash cell.
hash = hashN(cen, pos + CENHDR, nlen);
hsh = (hash & 0x7fffffff) % tablelen;
......
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
......@@ -297,7 +297,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
readFully(b, 0, len);
// Force to use UTF-8 if the USE_UTF8 bit is ON
ZipEntry e = createZipEntry(((flag & USE_UTF8) != 0)
? zc.toStringUTF8(b, len)
? ZipCoder.toStringUTF8(b, len)
: zc.toString(b, len));
// now get the remaining fields for the entry
if ((flag & 1) == 1) {
......
......@@ -1086,7 +1086,8 @@ class ZipFileSystem extends FileSystem {
int nlen = CENNAM(cen, pos);
int elen = CENEXT(cen, pos);
int clen = CENCOM(cen, pos);
if ((CENFLG(cen, pos) & 1) != 0) {
int flag = CENFLG(cen, pos);
if ((flag & 1) != 0) {
zerror("invalid CEN header (encrypted entry)");
}
if (method != METHOD_STORED && method != METHOD_DEFLATED) {
......@@ -1097,6 +1098,11 @@ class ZipFileSystem extends FileSystem {
}
IndexNode inode = new IndexNode(cen, pos, nlen);
inodes.put(inode, inode);
if (zc.isUTF8() || (flag & FLAG_USE_UTF8) != 0) {
checkUTF8(inode.name);
} else {
checkEncoding(inode.name);
}
// skip ext and comment
pos += (CENHDR + nlen + elen + clen);
}
......@@ -1107,6 +1113,34 @@ class ZipFileSystem extends FileSystem {
return cen;
}
private final void checkUTF8(byte[] a) throws ZipException {
try {
int end = a.length;
int pos = 0;
while (pos < end) {
// ASCII fast-path: When checking that a range of bytes is
// valid UTF-8, we can avoid some allocation by skipping
// past bytes in the 0-127 range
if (a[pos] < 0) {
zc.toString(Arrays.copyOfRange(a, pos, a.length));
break;
}
pos++;
}
} catch(Exception e) {
throw new ZipException("invalid CEN header (bad entry name)");
}
}
private final void checkEncoding( byte[] a) throws ZipException {
try {
zc.toString(a);
} catch(Exception e) {
throw new ZipException("invalid CEN header (bad entry name)");
}
}
private void ensureOpen() throws IOException {
if (!isOpen)
throw new ClosedFileSystemException();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册