Skip to content

Commit 2d240a0

Browse files
author
duke
committedMar 18, 2022
Automatic merge of jdk:master into master
2 parents f822663 + ff0b092 commit 2d240a0

File tree

5 files changed

+231
-154
lines changed

5 files changed

+231
-154
lines changed
 

‎src/java.base/share/classes/java/util/zip/Deflater.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2022, 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
@@ -895,6 +895,16 @@ private void ensureOpen() {
895895
throw new NullPointerException("Deflater has been closed");
896896
}
897897

898+
/**
899+
* Returns the value of 'finish' flag.
900+
* 'finish' will be set to true if def.finish() method is called.
901+
*/
902+
boolean shouldFinish() {
903+
synchronized (zsRef) {
904+
return finish;
905+
}
906+
}
907+
898908
private static native long init(int level, int strategy, boolean nowrap);
899909
private static native void setDictionary(long addr, byte[] b, int off,
900910
int len);

‎src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2022, 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
@@ -220,9 +220,15 @@ public void write(byte[] b, int off, int len) throws IOException {
220220
*/
221221
public void finish() throws IOException {
222222
if (!def.finished()) {
223-
def.finish();
224-
while (!def.finished()) {
225-
deflate();
223+
try{
224+
def.finish();
225+
while (!def.finished()) {
226+
deflate();
227+
}
228+
} catch(IOException e) {
229+
if (usesDefaultDeflater)
230+
def.end();
231+
throw e;
226232
}
227233
}
228234
}

‎src/java.base/share/classes/java/util/zip/ZipOutputStream.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2022, 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
@@ -314,7 +314,7 @@ public void closeEntry() throws IOException {
314314
crc.reset();
315315
current = null;
316316
} catch (IOException e) {
317-
if (usesDefaultDeflater && !(e instanceof ZipException))
317+
if (def.shouldFinish() && usesDefaultDeflater && !(e instanceof ZipException))
318318
def.end();
319319
throw e;
320320
}

‎test/jdk/java/util/zip/CloseDeflaterTest.java

-147
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test
26+
* @bug 8193682 8278794
27+
* @summary Test Infinite loop while writing on closed Deflater and Inflater.
28+
* @run testng CloseInflaterDeflaterTest
29+
*/
30+
import java.io.*;
31+
import java.util.Random;
32+
import java.util.jar.JarOutputStream;
33+
import java.util.zip.DeflaterInputStream;
34+
import java.util.zip.DeflaterOutputStream;
35+
import java.util.zip.GZIPOutputStream;
36+
import java.util.zip.InflaterOutputStream;
37+
import java.util.zip.ZipOutputStream;
38+
import java.util.zip.ZipEntry;
39+
40+
import org.testng.annotations.BeforeTest;
41+
import org.testng.annotations.DataProvider;
42+
import org.testng.annotations.Test;
43+
import static org.testng.Assert.assertThrows;
44+
45+
46+
public class CloseInflaterDeflaterTest {
47+
48+
// Number of bytes to write/read from Deflater/Inflater
49+
private static final int INPUT_LENGTH= 512;
50+
// OutputStream that will throw an exception during a write operation
51+
private static OutputStream outStream = new OutputStream() {
52+
@Override
53+
public void write(byte[] b, int off, int len) throws IOException {
54+
throw new IOException();
55+
}
56+
@Override
57+
public void write(byte[] b) throws IOException {}
58+
@Override
59+
public void write(int b) throws IOException {}
60+
};
61+
// InputStream that will throw an exception during a read operation
62+
private static InputStream inStream = new InputStream() {
63+
@Override
64+
public int read(byte[] b, int off, int len) throws IOException {
65+
throw new IOException();
66+
}
67+
@Override
68+
public int read(byte[] b) throws IOException { throw new IOException();}
69+
@Override
70+
public int read() throws IOException { throw new IOException();}
71+
};
72+
// Input bytes for read/write operation
73+
private static byte[] inputBytes = new byte[INPUT_LENGTH];
74+
// Random function to add bytes to inputBytes
75+
private static Random rand = new Random();
76+
77+
/**
78+
* DataProvider to specify whether to use close() or finish() of OutputStream
79+
*
80+
* @return Entry object indicating which method to use for closing OutputStream
81+
*/
82+
@DataProvider
83+
public Object[][] testOutputStreams() {
84+
return new Object[][] {
85+
{ true },
86+
{ false },
87+
};
88+
}
89+
90+
/**
91+
* DataProvider to specify on which outputstream closeEntry() has to be called
92+
*
93+
* @return Entry object returning either JarOutputStream or ZipOutputStream
94+
*/
95+
@DataProvider
96+
public Object[][] testZipAndJar() throws IOException{
97+
return new Object[][] {
98+
{ new JarOutputStream(outStream)},
99+
{ new ZipOutputStream(outStream)},
100+
};
101+
}
102+
103+
/**
104+
* Add inputBytes array with random bytes to write into OutputStream
105+
*/
106+
@BeforeTest
107+
public void before_test()
108+
{
109+
rand.nextBytes(inputBytes);
110+
}
111+
112+
/**
113+
* Test for infinite loop by writing bytes to closed GZIPOutputStream
114+
*
115+
* @param useCloseMethod indicates whether to use Close() or finish() method
116+
* @throws IOException if an error occurs
117+
*/
118+
@Test(dataProvider = "testOutputStreams")
119+
public void testGZip(boolean useCloseMethod) throws IOException {
120+
GZIPOutputStream gzip = new GZIPOutputStream(outStream);
121+
gzip.write(inputBytes, 0, INPUT_LENGTH);
122+
assertThrows(IOException.class, () -> {
123+
// Close GZIPOutputStream
124+
if (useCloseMethod) {
125+
gzip.close();
126+
} else {
127+
gzip.finish();
128+
}
129+
});
130+
// Write on a closed GZIPOutputStream, closed Deflater IOException expected
131+
assertThrows(NullPointerException.class , () -> gzip.write(inputBytes, 0, INPUT_LENGTH));
132+
}
133+
134+
/**
135+
* Test for infinite loop by writing bytes to closed DeflaterOutputStream
136+
*
137+
* @param useCloseMethod indicates whether to use Close() or finish() method
138+
* @throws IOException if an error occurs
139+
*/
140+
@Test(dataProvider = "testOutputStreams")
141+
public void testDeflaterOutputStream(boolean useCloseMethod) throws IOException {
142+
DeflaterOutputStream def = new DeflaterOutputStream(outStream);
143+
assertThrows(IOException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH));
144+
assertThrows(IOException.class, () -> {
145+
// Close DeflaterOutputStream
146+
if (useCloseMethod) {
147+
def.close();
148+
} else {
149+
def.finish();
150+
}
151+
});
152+
// Write on a closed DeflaterOutputStream, 'Deflater has been closed' NPE is expected
153+
assertThrows(NullPointerException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH));
154+
}
155+
156+
/**
157+
* Test for infinite loop by reading bytes from closed DeflaterInputStream
158+
*
159+
* @throws IOException if an error occurs
160+
*/
161+
@Test
162+
public void testDeflaterInputStream() throws IOException {
163+
DeflaterInputStream def = new DeflaterInputStream(inStream);
164+
assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH));
165+
// Close DeflaterInputStream
166+
def.close();
167+
// Read from a closed DeflaterInputStream, closed Deflater IOException expected
168+
assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH));
169+
}
170+
171+
/**
172+
* Test for infinite loop by writing bytes to closed InflaterOutputStream
173+
*
174+
* @param useCloseMethod indicates whether to use Close() or finish() method
175+
* @throws IOException if an error occurs
176+
*/
177+
@Test(dataProvider = "testOutputStreams")
178+
public void testInflaterOutputStream(boolean useCloseMethod) throws IOException {
179+
InflaterOutputStream inf = new InflaterOutputStream(outStream);
180+
assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH));
181+
assertThrows(IOException.class , () -> {
182+
// Close InflaterOutputStream
183+
if (useCloseMethod) {
184+
inf.close();
185+
} else {
186+
inf.finish();
187+
}
188+
});
189+
// Write on a closed InflaterOutputStream , closed Inflater IOException expected
190+
assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH));
191+
}
192+
193+
/**
194+
* Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream
195+
*
196+
* @param zip will be the instance of either JarOutputStream or ZipOutputStream
197+
* @throws IOException if an error occurs
198+
*/
199+
@Test(dataProvider = "testZipAndJar")
200+
public void testZipCloseEntry(ZipOutputStream zip) throws IOException {
201+
assertThrows(IOException.class , () -> zip.putNextEntry(new ZipEntry("")));
202+
zip.write(inputBytes, 0, INPUT_LENGTH);
203+
assertThrows(IOException.class , () -> zip.closeEntry());
204+
// Write on a closed ZipOutputStream , 'Deflater has been closed' NPE is expected
205+
assertThrows(NullPointerException.class , () -> zip.write(inputBytes, 0, INPUT_LENGTH));
206+
}
207+
208+
}

0 commit comments

Comments
 (0)
Please sign in to comment.