This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-vfs.git
The following commit(s) were added to refs/heads/master by this push: new 8f21755 [VFS-744] org.apache.commons.vfs2.FileContent.getByteArray() can throw NegativeArraySizeException for BZip2 files 8f21755 is described below commit 8f217556c4d3a476c64862c8181821cd0e6adada Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Thu Oct 17 19:03:31 2019 -0400 [VFS-744] org.apache.commons.vfs2.FileContent.getByteArray() can throw NegativeArraySizeException for BZip2 files --- .../java/org/apache/commons/vfs2/FileContent.java | 32 ++++++----- .../commons/vfs2/provider/AbstractFileObject.java | 2 +- .../compressed/CompressedFileFileObject.java | 2 +- .../commons/vfs2/provider/bzip2/Bzip2TestCase.java | 59 +++++++++++++++++++++ .../src/test/resources/test-data/bla.txt.bz2 | Bin 0 -> 66 bytes src/changes/changes.xml | 3 ++ 6 files changed, 82 insertions(+), 16 deletions(-) diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileContent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileContent.java index 0162f3c..7e571f0 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileContent.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileContent.java @@ -22,8 +22,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.security.cert.Certificate; +import java.util.Arrays; import java.util.Map; +import org.apache.commons.vfs2.provider.AbstractFileObject; import org.apache.commons.vfs2.util.RandomAccessMode; /** @@ -92,15 +94,17 @@ public interface FileContent extends Closeable { if (sizeL > Integer.MAX_VALUE) { throw new IllegalStateException(String.format("File content is too large for a byte array: %,d", sizeL)); } - final int size = (int) sizeL; + final boolean sizeUndefined = sizeL < 0; + final int size = sizeUndefined ? AbstractFileObject.DEFAULT_BUFFER_SIZE : (int) sizeL; final byte[] buf = new byte[size]; + int pos; try (final InputStream in = getInputStream(size)) { int read = 0; - for (int pos = 0; pos < size && read >= 0; pos += read) { + for (pos = 0; pos < size && read >= 0; pos += read) { read = in.read(buf, pos, size - pos); } } - return buf; + return sizeUndefined && pos < buf.length ? Arrays.copyOf(buf, ++pos) : buf; } /** @@ -135,7 +139,7 @@ public interface FileContent extends Closeable { * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to * wrap it in a {@code BufferedInputStream}. * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error - * opening the stream. + * opening the stream. */ InputStream getInputStream() throws FileSystemException; @@ -149,7 +153,7 @@ public interface FileContent extends Closeable { * @return An input stream to read the file's content from. The input stream is buffered, so there is no need to * wrap it in a {@code BufferedInputStream}. * @throws FileSystemException If the file does not exist, or is being read, or is being written, or on error - * opening the stream. + * opening the stream. * @since 2.4 */ default InputStream getInputStream(final int bufferSize) throws FileSystemException { @@ -161,7 +165,7 @@ public interface FileContent extends Closeable { * * @return The last-modified timestamp. * @throws FileSystemException If the file does not exist, or is being written to, or on error determining the - * last-modified timestamp. + * last-modified timestamp. */ long getLastModifiedTime() throws FileSystemException; @@ -178,7 +182,7 @@ public interface FileContent extends Closeable { * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it * in a {@code BufferedOutputStream}. * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening - * the stream. + * the stream. */ OutputStream getOutputStream() throws FileSystemException; @@ -196,7 +200,7 @@ public interface FileContent extends Closeable { * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it * in a {@code BufferedOutputStream}. * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true - * and the implementation does not support it, or on error opening the stream. + * and the implementation does not support it, or on error opening the stream. */ OutputStream getOutputStream(boolean bAppend) throws FileSystemException; @@ -215,7 +219,7 @@ public interface FileContent extends Closeable { * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it * in a {@code BufferedOutputStream}. * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true - * and the implementation does not support it, or on error opening the stream. + * and the implementation does not support it, or on error opening the stream. * @since 2.4 */ default OutputStream getOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException { @@ -236,7 +240,7 @@ public interface FileContent extends Closeable { * @return An output stream to write the file's content to. The stream is buffered, so there is no need to wrap it * in a {@code BufferedOutputStream}. * @throws FileSystemException If the file is read-only, or is being read, or is being written, or bAppend is true - * and the implementation does not support it, or on error opening the stream. + * and the implementation does not support it, or on error opening the stream. * @since 2.4 */ default OutputStream getOutputStream(final int bufferSize) throws FileSystemException { @@ -257,7 +261,7 @@ public interface FileContent extends Closeable { * @param mode The mode to use to access the file. * @return the stream for reading and writing the file's content. * @throws FileSystemException If the file is read-only, or is being read, or is being written, or on error opening - * the stream. + * the stream. */ RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException; @@ -325,7 +329,7 @@ public interface FileContent extends Closeable { * * @param attrName The name of the attribute. * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on - * error removing the attribute. + * error removing the attribute. */ void removeAttribute(String attrName) throws FileSystemException; @@ -335,7 +339,7 @@ public interface FileContent extends Closeable { * @param attrName The name of the attribute. * @param value The value of the attribute. * @throws FileSystemException If the file does not exist, or is read-only, or does not support attributes, or on - * error setting the attribute. + * error setting the attribute. */ void setAttribute(String attrName, Object value) throws FileSystemException; @@ -344,7 +348,7 @@ public interface FileContent extends Closeable { * * @param modTime The time to set the last-modified timestamp to. * @throws FileSystemException If the file is read-only, or is being written to, or on error setting the - * last-modified timestamp. + * last-modified timestamp. */ void setLastModifiedTime(long modTime) throws FileSystemException; diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java index f27c4de..04376b5 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java @@ -70,7 +70,7 @@ public abstract class AbstractFileObject<AFS extends AbstractFileSystem> impleme /** * Same as {@link BufferedInputStream}. */ - private static final int DEFAULT_BUFFER_SIZE = 8192; + public static final int DEFAULT_BUFFER_SIZE = 8192; private static final FileName[] EMPTY_FILE_ARRAY = {}; diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java index 3c03485..45de078 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java @@ -36,7 +36,7 @@ public abstract class CompressedFileFileObject<FS extends CompressedFileFileSyst /** * The value returned by {@link #doGetContentSize()} when not overriden by a subclass. - * + * * @since 2.5.0 */ public static final int SIZE_UNDEFINED = -1; diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/bzip2/Bzip2TestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/bzip2/Bzip2TestCase.java new file mode 100644 index 0000000..a6b10d8 --- /dev/null +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/bzip2/Bzip2TestCase.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.vfs2.provider.bzip2; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.AbstractVfsTestCase; +import org.apache.commons.vfs2.FileContent; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.VFS; +import org.apache.commons.vfs2.provider.compressed.CompressedFileFileObject; +import org.junit.Assert; +import org.junit.Test; + +public class Bzip2TestCase extends AbstractVfsTestCase { + + @Test + public void testBZip2() throws IOException { + final File testResource = getTestResource("bla.txt.bz2"); + try (final FileObject bz2FileObject = VFS.getManager().resolveFile("bz2://" + testResource)) { + Assert.assertTrue(bz2FileObject.exists()); + Assert.assertTrue(bz2FileObject.isFolder()); + try (final FileObject fileObjectDir = bz2FileObject.resolveFile("bla.txt")) { + Assert.assertTrue(fileObjectDir.exists()); + Assert.assertTrue(bz2FileObject.isFolder()); + try (final FileObject fileObject = fileObjectDir.resolveFile("bla.txt")) { + Assert.assertTrue(fileObject.exists()); + Assert.assertFalse(fileObject.isFolder()); + Assert.assertTrue(fileObject.isFile()); + try (final FileContent content = fileObject.getContent()) { + Assert.assertEquals(CompressedFileFileObject.SIZE_UNDEFINED, content.getSize()); + // blows up, Commons Compress? + final String string = content.getString(StandardCharsets.UTF_8); + Assert.assertEquals(26, string.length()); + Assert.assertEquals("Hallo, dies ist ein Test.\n", string); + } + } + } + } + } + +} diff --git a/commons-vfs2/src/test/resources/test-data/bla.txt.bz2 b/commons-vfs2/src/test/resources/test-data/bla.txt.bz2 new file mode 100644 index 0000000..87309da Binary files /dev/null and b/commons-vfs2/src/test/resources/test-data/bla.txt.bz2 differ diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9fc9f3f..00f1ff6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -110,6 +110,9 @@ The <action> type attribute can be add,update,fix,remove. <action issue="VFS-743" dev="ggregory" type="add" due-to="Gary Gregory"> Add org.apache.commons.vfs2.provider.compressed.CompressedFileFileObject.SIZE_UNDEFINED. </action> + <action issue="VFS-744" dev="ggregory" type="fix" due-to="Gary Gregory"> + org.apache.commons.vfs2.FileContent.getByteArray() can throw NegativeArraySizeException for BZip2 files. + </action> </release> <release version="2.4.1" date="2019-08-10" description="Bug fix release."> <action issue="VFS-725" dev="ggregory" type="fix" due-to="Gary Gregory">