View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.compress.compressors.bzip2;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.ByteArrayOutputStream;
27  import java.io.File;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.nio.file.Files;
31  
32  import org.apache.commons.compress.AbstractTest;
33  import org.apache.commons.compress.archivers.ArchiveException;
34  import org.apache.commons.compress.archivers.ArchiveInputStream;
35  import org.apache.commons.compress.archivers.ArchiveStreamFactory;
36  import org.apache.commons.io.IOUtils;
37  import org.junit.jupiter.api.Test;
38  
39  class BZip2CompressorInputStreamTest extends AbstractTest {
40  
41      private void fuzzingTest(final int[] bytes) throws IOException, ArchiveException {
42          final int len = bytes.length;
43          final byte[] input = new byte[len];
44          for (int i = 0; i < len; i++) {
45              input[i] = (byte) bytes[i];
46          }
47          try (ArchiveInputStream<?> ais = ArchiveStreamFactory.DEFAULT.createArchiveInputStream("zip", new ByteArrayInputStream(input))) {
48              ais.getNextEntry();
49              IOUtils.toByteArray(ais);
50          }
51      }
52  
53      @Test
54      void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws IOException {
55          final File input = getFile("bla.txt.bz2");
56          final byte[] buf = new byte[2];
57          try (InputStream is = Files.newInputStream(input.toPath());
58                  BZip2CompressorInputStream in = new BZip2CompressorInputStream(is)) {
59              IOUtils.toByteArray(in);
60              assertEquals(-1, in.read(buf));
61              assertEquals(-1, in.read(buf));
62          }
63      }
64  
65      /**
66       * @see "https://issues.apache.org/jira/browse/COMPRESS-309"
67       */
68      @Test
69      void testReadOfLength0ShouldReturn0() throws Exception {
70          // Create a big random piece of data
71          final byte[] rawData = new byte[1048576];
72          for (int i = 0; i < rawData.length; ++i) {
73              rawData[i] = (byte) Math.floor(Math.random() * 256);
74          }
75  
76          // Compress it
77          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
78          try (BZip2CompressorOutputStream bzipOut = new BZip2CompressorOutputStream(baos)) {
79              bzipOut.write(rawData);
80              bzipOut.flush();
81              bzipOut.close();
82              assertTrue(bzipOut.isClosed());
83              baos.flush();
84          }
85  
86          // Try to read it back in
87          final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
88          try (BZip2CompressorInputStream bzipIn = new BZip2CompressorInputStream(bais)) {
89              final byte[] buffer = new byte[1024];
90              assertEquals(1024, bzipIn.read(buffer, 0, 1024));
91              assertEquals(0, bzipIn.read(buffer, 1024, 0));
92              assertEquals(1024, bzipIn.read(buffer, 0, 1024));
93          }
94      }
95  
96      @Test
97      void testShouldThrowAnIOExceptionWhenAppliedToAZipFile() throws Exception {
98          try (InputStream in = newInputStream("bla.zip")) {
99              assertThrows(IOException.class, () -> new BZip2CompressorInputStream(in));
100         }
101     }
102 
103     /**
104      * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-516">COMPRESS-516</a>
105      */
106     @Test
107     void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS516() {
108         assertThrows(IOException.class,
109                 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
110                         0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
111                         0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
112                         0x68, 0x34, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x62, 0xe4, 0x4f, 0x51, 0x00, 0x00, 0x0d, 0xd1, 0x80, 0x00, 0x10, 0x40, 0x00, 0x35,
113                         0xf9, 0x8b, 0x00, 0x20, 0x00, 0x48, 0x89, 0xfa, 0x94, 0xf2, 0x9e, 0x29, 0xe8, 0xd2, 0x11, 0x8a, 0x4f, 0x53, 0x34, 0x0f, 0x51, 0x7a,
114                         0xed, 0x86, 0x65, 0xd6, 0xed, 0x61, 0xee, 0x68, 0x89, 0x48, 0x7d, 0x07, 0x71, 0x92, 0x2a, 0x50, 0x60, 0x04, 0x95, 0x61, 0x35, 0x47,
115                         0x73, 0x31, 0x29, 0xc2, 0xdd, 0x5e, 0xc7, 0x4a, 0x15, 0x14, 0x32, 0x4c, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }));
116     }
117 
118     /**
119      * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-519">COMPRESS-519</a>
120      */
121     @Test
122     void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS519() {
123         assertThrows(IOException.class,
124                 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
125                         0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
126                         0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
127                         0x68, 0x34, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x62, 0xe4, 0x4f, 0x51, 0x80, 0x00, 0x0d, 0xd1, 0x80, 0x00, 0x10, 0x40, 0x00, 0x35,
128                         0xf9, 0x8b, 0x00, 0x20, 0x00, 0x48, 0x89, 0xfa, 0x94, 0xf2, 0x9e, 0x29, 0xe8, 0xd2, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x50, 0x4b,
129                         0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }));
130     }
131 
132     @Test
133     void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws IOException {
134         final File input = getFile("bla.txt.bz2");
135         try (InputStream is = Files.newInputStream(input.toPath());
136                 BZip2CompressorInputStream in = new BZip2CompressorInputStream(is)) {
137             IOUtils.toByteArray(in);
138             assertEquals(-1, in.read());
139             assertEquals(-1, in.read());
140         }
141     }
142 }