You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2019/02/18 17:08:19 UTC
[commons-compress] branch master updated: Removed incorrect use of
InputStream.available() in ArArchiveInputStream
This is an automated email from the ASF dual-hosted git repository.
bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push:
new 8e5338c Removed incorrect use of InputStream.available() in ArArchiveInputStream
new 575f0eb Merge pull request #74 from akbertram/patch-1
8e5338c is described below
commit 8e5338cd2d6edc347cfe2bcd72f15bf23b178f5b
Author: Alex Bertram <al...@bedatadriven.com>
AuthorDate: Mon Feb 11 20:22:48 2019 +0100
Removed incorrect use of InputStream.available() in ArArchiveInputStream
The original code appears to be checking for end-of-file
using the InputStream.available() method.
This however, misunderstands the InputStream API. The available()
method only returns an estimate, and cannot be used
to check for the remaining bytes in the file. From the documentation:
> Returns an estimate of the number of bytes that can be read (or
> skipped over) from this input stream without blocking by the next
> invocation of a method for this input stream. The next invocation
> might be the same thread or another thread. A single read or skip of this
> many bytes will not block, but may read or skip fewer bytes.
> Note that while some implementations of InputStream will return
> the total number of bytes in the stream, many will not. It is
> never correct to use the return value of this method to allocate
> a buffer intended to hold all data in this stream.
This patch includes a unit test that demonstrates the bug and
verifies the fix.
---
.../archivers/ar/ArArchiveInputStream.java | 7 ++---
.../archivers/ar/ArArchiveInputStreamTest.java | 32 ++++++++++++++++++++--
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
index 206d388..38d13d9 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
@@ -121,13 +121,12 @@ public class ArArchiveInputStream extends ArchiveInputStream {
trackReadBytes(1);
}
- if (input.available() == 0) {
- return null;
- }
-
{
final int read = IOUtils.readFully(input, metaData);
trackReadBytes(read);
+ if (read == 0) {
+ return null;
+ }
if (read < metaData.length) {
throw new IOException("truncated ar archive");
}
diff --git a/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
index e665ff9..14c4315 100644
--- a/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
@@ -18,10 +18,10 @@
package org.apache.commons.compress.archivers.ar;
+import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
+import java.io.*;
import org.apache.commons.compress.AbstractTestCase;
import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -83,6 +83,34 @@ public class ArArchiveInputStreamTest extends AbstractTestCase {
}
}
+ @Test
+ public void simpleInputStream() throws IOException {
+ try (final FileInputStream fileInputStream = new FileInputStream(getFile("bla.ar"))) {
+
+ // This default implementation of InputStream.available() always returns zero,
+ // and there are many streams in practice where the total length of the stream is not known.
+
+ final InputStream simpleInputStream = new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return fileInputStream.read();
+ }
+ };
+
+ ArArchiveInputStream archiveInputStream = new ArArchiveInputStream(simpleInputStream);
+ ArArchiveEntry entry1 = archiveInputStream.getNextArEntry();
+ assertThat(entry1, not(nullValue()));
+ assertThat(entry1.getName(), equalTo("test1.xml"));
+ assertThat(entry1.getLength(), equalTo(610L));
+
+ ArArchiveEntry entry2 = archiveInputStream.getNextArEntry();
+ assertThat(entry2.getName(), equalTo("test2.xml"));
+ assertThat(entry2.getLength(), equalTo(82L));
+
+ assertThat(archiveInputStream.getNextArEntry(), nullValue());
+ }
+ }
+
@Test(expected=IllegalStateException.class)
public void cantReadWithoutOpeningAnEntry() throws Exception {
try (FileInputStream in = new FileInputStream(getFile("bla.ar"));