Skip to content

Commit 96cbbef

Browse files
Yuxi Suncopybara-github
authored andcommitted
Upgrade java.util.zip package
#J2ObjC_Android13_JRE_Upgrade_2022 PiperOrigin-RevId: 549022208
1 parent bbc8cca commit 96cbbef

23 files changed

+1230
-470
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package dalvik.system;
18+
19+
import libcore.util.NonNull;
20+
21+
import java.util.Objects;
22+
import java.util.zip.ZipException;
23+
24+
/**
25+
* Enables validation of zip file entry paths to prevent exploitation of the path traversal
26+
* vulnerability, e.g. zip path entries containing ".." or "/". For more details, read
27+
* <a href="https://developer.android.com/topic/security/risks/zip-path-traversal">this</a>.
28+
* <p>
29+
* The default implementation accepts all zip file entry paths without raising any exceptions.
30+
* <p>
31+
* For custom validation rules, the core functionality should be implemented in a {@link Callback}
32+
* interface and that instance should be set in {@link #setCallback(Callback)}.
33+
* <p>
34+
* Existing validation could be set to a default one by calling {@link #clearCallback()}.
35+
*/
36+
public final class ZipPathValidator {
37+
38+
/**
39+
* Default implementation of the {@link Callback} interface which accepts all paths.
40+
*
41+
* @hide
42+
*/
43+
public static final Callback DEFAULT = new Callback() {};
44+
45+
private static volatile Callback sInstance = DEFAULT;
46+
47+
/**
48+
* Clears the current validation mechanism by setting the current callback instance to a default
49+
* validation.
50+
*/
51+
public static void clearCallback() {
52+
sInstance = DEFAULT;
53+
}
54+
55+
/**
56+
* Sets the current callback implementation for zip paths.
57+
* <p>
58+
* The provided callback should not perform IO or any blocking operations, but only perform path
59+
* validation. A typical implementation will validate String entries in a single pass and throw
60+
* a {@link ZipException} if the path contains potentially hazardous components such as "..".
61+
*
62+
* @param callback An instance of {@link Callback}'s implementation.
63+
*/
64+
public static void setCallback(@NonNull Callback callback) {
65+
sInstance = Objects.requireNonNull(callback);
66+
}
67+
68+
/**
69+
* Retrieves the current validator set by {@link #setCallback(Callback)}.
70+
*
71+
* @return Current callback.
72+
*
73+
* @hide
74+
*/
75+
public static @NonNull Callback getInstance() {
76+
return sInstance;
77+
}
78+
79+
/**
80+
* Returns true if the current validator is the default implementation {@link DEFAULT},
81+
* otherwise false.
82+
*
83+
* @hide
84+
*/
85+
public static boolean isClear() {
86+
return sInstance.equals(DEFAULT);
87+
}
88+
89+
/**
90+
* Interface that defines the core validation mechanism when accessing zip file entry paths.
91+
*/
92+
public interface Callback {
93+
/**
94+
* Called to check the validity of the path of a zip entry. The default implementation
95+
* accepts all paths without raising any exceptions.
96+
* <p>
97+
* This method will be called by {@link java.util.zip.ZipInputStream#getNextEntry} or
98+
* {@link java.util.zip.ZipFile#ZipFile(String)}.
99+
*
100+
* @param path The name of the zip entry.
101+
* @throws ZipException If the zip entry is invalid depending on the implementation.
102+
*/
103+
default void onZipEntryAccess(@NonNull String path) throws ZipException {}
104+
}
105+
106+
private ZipPathValidator() {}
107+
}

jre_emul/android/platform/libcore/ojluni/src/main/java/java/util/zip/CheckedInputStream.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,9 @@
3535
*
3636
* @see Checksum
3737
* @author David Connelly
38+
* @since 1.1
3839
*/
39-
public
40-
class CheckedInputStream extends FilterInputStream {
40+
public class CheckedInputStream extends FilterInputStream {
4141
private Checksum cksum;
4242

4343
/**
@@ -53,7 +53,7 @@ public CheckedInputStream(InputStream in, Checksum cksum) {
5353
/**
5454
* Reads a byte. Will block if no input is available.
5555
* @return the byte read, or -1 if the end of the stream is reached.
56-
* @exception IOException if an I/O error has occurred
56+
* @throws IOException if an I/O error has occurred
5757
*/
5858
public int read() throws IOException {
5959
int b = in.read();
@@ -64,19 +64,19 @@ public int read() throws IOException {
6464
}
6565

6666
/**
67-
* Reads into an array of bytes. If <code>len</code> is not zero, the method
67+
* Reads into an array of bytes. If {@code len} is not zero, the method
6868
* blocks until some input is available; otherwise, no
69-
* bytes are read and <code>0</code> is returned.
69+
* bytes are read and {@code 0} is returned.
7070
* @param buf the buffer into which the data is read
71-
* @param off the start offset in the destination array <code>b</code>
71+
* @param off the start offset in the destination array {@code b}
7272
* @param len the maximum number of bytes read
7373
* @return the actual number of bytes read, or -1 if the end
7474
* of the stream is reached.
75-
* @exception NullPointerException If <code>buf</code> is <code>null</code>.
76-
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
77-
* <code>len</code> is negative, or <code>len</code> is greater than
78-
* <code>buf.length - off</code>
79-
* @exception IOException if an I/O error has occurred
75+
* @throws NullPointerException If {@code buf} is {@code null}.
76+
* @throws IndexOutOfBoundsException If {@code off} is negative,
77+
* {@code len} is negative, or {@code len} is greater than
78+
* {@code buf.length - off}
79+
* @throws IOException if an I/O error has occurred
8080
*/
8181
public int read(byte[] buf, int off, int len) throws IOException {
8282
len = in.read(buf, off, len);
@@ -90,7 +90,7 @@ public int read(byte[] buf, int off, int len) throws IOException {
9090
* Skips specified number of bytes of input.
9191
* @param n the number of bytes to skip
9292
* @return the actual number of bytes skipped
93-
* @exception IOException if an I/O error has occurred
93+
* @throws IOException if an I/O error has occurred
9494
*/
9595
public long skip(long n) throws IOException {
9696
byte[] buf = new byte[512];
@@ -113,4 +113,4 @@ public long skip(long n) throws IOException {
113113
public Checksum getChecksum() {
114114
return cksum;
115115
}
116-
}
116+
}

jre_emul/android/platform/libcore/ojluni/src/main/java/java/util/zip/CheckedOutputStream.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,9 +36,9 @@
3636
*
3737
* @see Checksum
3838
* @author David Connelly
39+
* @since 1.1
3940
*/
40-
public
41-
class CheckedOutputStream extends FilterOutputStream {
41+
public class CheckedOutputStream extends FilterOutputStream {
4242
private Checksum cksum;
4343

4444
/**
@@ -54,7 +54,7 @@ public CheckedOutputStream(OutputStream out, Checksum cksum) {
5454
/**
5555
* Writes a byte. Will block until the byte is actually written.
5656
* @param b the byte to be written
57-
* @exception IOException if an I/O error has occurred
57+
* @throws IOException if an I/O error has occurred
5858
*/
5959
public void write(int b) throws IOException {
6060
out.write(b);
@@ -67,7 +67,7 @@ public void write(int b) throws IOException {
6767
* @param b the data to be written
6868
* @param off the start offset of the data
6969
* @param len the number of bytes to be written
70-
* @exception IOException if an I/O error has occurred
70+
* @throws IOException if an I/O error has occurred
7171
*/
7272
public void write(byte[] b, int off, int len) throws IOException {
7373
out.write(b, off, len);
@@ -81,4 +81,4 @@ public void write(byte[] b, int off, int len) throws IOException {
8181
public Checksum getChecksum() {
8282
return cksum;
8383
}
84-
}
84+
}

jre_emul/android/platform/libcore/ojluni/src/main/java/java/util/zip/Checksum.java

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,18 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25-
2625
package java.util.zip;
2726

27+
import java.nio.ByteBuffer;
28+
2829
/**
2930
* An interface representing a data checksum.
3031
*
31-
* @author David Connelly
32+
* @author David Connelly
33+
* @since 1.1
3234
*/
33-
public
34-
interface Checksum {
35+
public interface Checksum {
36+
3537
/**
3638
* Updates the current checksum with the specified byte.
3739
*
@@ -41,14 +43,89 @@ interface Checksum {
4143

4244
/**
4345
* Updates the current checksum with the specified array of bytes.
46+
*
47+
* @implSpec This default implementation is equal to calling
48+
* {@code update(b, 0, b.length)}.
49+
*
50+
* @param b the array of bytes to update the checksum with
51+
*
52+
* @throws NullPointerException
53+
* if {@code b} is {@code null}
54+
*
55+
* @since 9
56+
*/
57+
default public void update(byte[] b) {
58+
update(b, 0, b.length);
59+
}
60+
61+
/**
62+
* Updates the current checksum with the specified array of bytes.
63+
*
4464
* @param b the byte array to update the checksum with
4565
* @param off the start offset of the data
4666
* @param len the number of bytes to use for the update
4767
*/
4868
public void update(byte[] b, int off, int len);
4969

70+
/**
71+
* Updates the current checksum with the bytes from the specified buffer.
72+
*
73+
* The checksum is updated with the remaining bytes in the buffer, starting
74+
* at the buffer's position. Upon return, the buffer's position will be
75+
* updated to its limit; its limit will not have been changed.
76+
*
77+
* @apiNote For best performance with DirectByteBuffer and other ByteBuffer
78+
* implementations without a backing array implementers of this interface
79+
* should override this method.
80+
*
81+
* @implSpec The default implementation has the following behavior.<br>
82+
* For ByteBuffers backed by an accessible byte array.
83+
* <pre>{@code
84+
* update(buffer.array(),
85+
* buffer.position() + buffer.arrayOffset(),
86+
* buffer.remaining());
87+
* }</pre>
88+
* For ByteBuffers not backed by an accessible byte array.
89+
* <pre>{@code
90+
* byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
91+
* while (buffer.hasRemaining()) {
92+
* int length = Math.min(buffer.remaining(), b.length);
93+
* buffer.get(b, 0, length);
94+
* update(b, 0, length);
95+
* }
96+
* }</pre>
97+
*
98+
* @param buffer the ByteBuffer to update the checksum with
99+
*
100+
* @throws NullPointerException
101+
* if {@code buffer} is {@code null}
102+
*
103+
* @since 9
104+
*/
105+
default public void update(ByteBuffer buffer) {
106+
int pos = buffer.position();
107+
int limit = buffer.limit();
108+
assert (pos <= limit);
109+
int rem = limit - pos;
110+
if (rem <= 0) {
111+
return;
112+
}
113+
if (buffer.hasArray()) {
114+
update(buffer.array(), pos + buffer.arrayOffset(), rem);
115+
} else {
116+
byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
117+
while (buffer.hasRemaining()) {
118+
int length = Math.min(buffer.remaining(), b.length);
119+
buffer.get(b, 0, length);
120+
update(b, 0, length);
121+
}
122+
}
123+
buffer.position(limit);
124+
}
125+
50126
/**
51127
* Returns the current checksum value.
128+
*
52129
* @return the current checksum value
53130
*/
54131
public long getValue();
@@ -57,4 +134,4 @@ interface Checksum {
57134
* Resets the checksum to its initial value.
58135
*/
59136
public void reset();
60-
}
137+
}

jre_emul/android/platform/libcore/ojluni/src/main/java/java/util/zip/DataFormatException.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,10 @@
2929
* Signals that a data format error has occurred.
3030
*
3131
* @author David Connelly
32+
* @since 1.1
3233
*/
33-
public
34-
class DataFormatException extends Exception {
34+
public class DataFormatException extends Exception {
35+
@java.io.Serial
3536
private static final long serialVersionUID = 2219632870893641452L;
3637

3738
/**
@@ -49,4 +50,4 @@ public DataFormatException() {
4950
public DataFormatException(String s) {
5051
super(s);
5152
}
52-
}
53+
}

0 commit comments

Comments
 (0)