summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-03-10 13:18:53 +0000
committerNarayan Kamath <narayan@google.com>2014-03-10 18:54:45 +0000
commitbb65253db600d05ca6eeedc6d076f6af20680f99 (patch)
tree795dcd39613e038f632f154b40acf0c5b2abaf71 /luni
parentefa075cb4c3d51560c12c7b3808e5e7e084b5808 (diff)
downloadlibcore-bb65253db600d05ca6eeedc6d076f6af20680f99.zip
libcore-bb65253db600d05ca6eeedc6d076f6af20680f99.tar.gz
libcore-bb65253db600d05ca6eeedc6d076f6af20680f99.tar.bz2
Use the correct buffer size for the Pushback stream.
The maximum number of bytes we can push back to the stream is the actual size of the DeflaterInputStream buffer (buf.length) and not the default size (BUF_LENGTH). bug: https://code.google.com/p/android/issues/detail?id=66409 Change-Id: I78a80b6ced8606602361abd8a969fa6f8227596c
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/java/java/util/zip/GZIPInputStream.java10
-rw-r--r--luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java49
2 files changed, 56 insertions, 3 deletions
diff --git a/luni/src/main/java/java/util/zip/GZIPInputStream.java b/luni/src/main/java/java/util/zip/GZIPInputStream.java
index 790adb2..1bfc496 100644
--- a/luni/src/main/java/java/util/zip/GZIPInputStream.java
+++ b/luni/src/main/java/java/util/zip/GZIPInputStream.java
@@ -166,10 +166,14 @@ public class GZIPInputStream extends InflaterInputStream {
// successfully consumed the GZIP trailer.
final int remaining = inf.getRemaining() - GZIP_TRAILER_SIZE;
if (remaining > 0) {
- // NOTE: This prevents us from creating multiple layers of nested
- // PushbackInputStreams if we have multiple members in this stream.
+ // NOTE: We make sure we create a pushback stream exactly once,
+ // even if the input stream contains multiple members.
+ //
+ // The push back stream we create must therefore be able to contain
+ // (worst case) the entire buffer even though there may be fewer bytes
+ // remaining when it is first created.
if (!(in instanceof PushbackInputStream)) {
- in = new PushbackInputStream(in, BUF_SIZE);
+ in = new PushbackInputStream(in, buf.length);
}
((PushbackInputStream) in).unread(buf,
inf.getCurrentOffset() + GZIP_TRAILER_SIZE, remaining);
diff --git a/luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java
index b2e012e..494520a 100644
--- a/luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java
@@ -19,12 +19,18 @@ package libcore.java.util.zip;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Random;
import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
import junit.framework.TestCase;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
public final class GZIPInputStreamTest extends TestCase {
@@ -112,6 +118,49 @@ public final class GZIPInputStreamTest extends TestCase {
}
}
+ // https://code.google.com/p/android/issues/detail?id=66409
+ public void testMultipleMembersWithCustomBufferSize() throws Exception {
+ final int[] memberSizes = new int[] { 1000, 2000 };
+
+ // We don't care what the exact contents of this file is, as long
+ // as the file has multiple members, and that the (compressed) size of
+ // the second member is larger than the size of the input buffer.
+ //
+ // There's no way to achieve this for a GZIPOutputStream so we generate
+ // pseudo-random sequence of bytes and assert that they don't compress
+ // well.
+ final Random r = new Random(10);
+ byte[] bytes = new byte[3000];
+ r.nextBytes(bytes);
+
+ File f = File.createTempFile("GZIPInputStreamTest", ".gzip");
+ int offset = 0;
+ for (int size : memberSizes) {
+ GZIPOutputStream gzos = null;
+ try {
+ FileOutputStream fos = new FileOutputStream(f, true /* append */);
+ gzos = new GZIPOutputStream(fos, size + 1);
+ gzos.write(bytes, offset, size);
+ offset += size;
+ gzos.finish();
+ } finally {
+ IoUtils.closeQuietly(gzos);
+ }
+ }
+
+ assertTrue(f.length() > 2048);
+
+ FileInputStream fis = new FileInputStream(f);
+ GZIPInputStream gzip = null;
+ try {
+ gzip = new GZIPInputStream(fis, memberSizes[0]);
+ byte[] unzipped = Streams.readFully(gzip);
+ assertTrue(Arrays.equals(bytes, unzipped));
+ } finally {
+ IoUtils.closeQuietly(gzip);
+ }
+ }
+
public static byte[] gunzip(byte[] bytes) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
InputStream in = new GZIPInputStream(bis);