diff options
author | Narayan Kamath <narayan@google.com> | 2014-03-10 13:18:53 +0000 |
---|---|---|
committer | Narayan Kamath <narayan@google.com> | 2014-03-10 18:54:45 +0000 |
commit | bb65253db600d05ca6eeedc6d076f6af20680f99 (patch) | |
tree | 795dcd39613e038f632f154b40acf0c5b2abaf71 /luni | |
parent | efa075cb4c3d51560c12c7b3808e5e7e084b5808 (diff) | |
download | libcore-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.java | 10 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/util/zip/GZIPInputStreamTest.java | 49 |
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); |