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   * http://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  
24  import java.io.ByteArrayInputStream;
25  import java.io.ByteArrayOutputStream;
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.nio.file.Files;
30  
31  import org.apache.commons.compress.AbstractTest;
32  import org.apache.commons.compress.archivers.ArchiveException;
33  import org.apache.commons.compress.archivers.ArchiveInputStream;
34  import org.apache.commons.compress.archivers.ArchiveStreamFactory;
35  import org.apache.commons.io.IOUtils;
36  import org.junit.jupiter.api.Test;
37  
38  public class BZip2CompressorInputStreamTest extends AbstractTest {
39  
40      private void fuzzingTest(final int[] bytes) throws IOException, ArchiveException {
41          final int len = bytes.length;
42          final byte[] input = new byte[len];
43          for (int i = 0; i < len; i++) {
44              input[i] = (byte) bytes[i];
45          }
46          try (ArchiveInputStream<?> ais = ArchiveStreamFactory.DEFAULT.createArchiveInputStream("zip", new ByteArrayInputStream(input))) {
47              ais.getNextEntry();
48              IOUtils.toByteArray(ais);
49          }
50      }
51  
52      @Test
53      public void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws IOException {
54          final File input = getFile("bla.txt.bz2");
55          final byte[] buf = new byte[2];
56          try (InputStream is = Files.newInputStream(input.toPath());
57                  BZip2CompressorInputStream in = new BZip2CompressorInputStream(is)) {
58              IOUtils.toByteArray(in);
59              assertEquals(-1, in.read(buf));
60              assertEquals(-1, in.read(buf));
61          }
62      }
63  
64      /**
65       * @see "https://issues.apache.org/jira/browse/COMPRESS-309"
66       */
67      @Test
68      public void testReadOfLength0ShouldReturn0() throws Exception {
69          // Create a big random piece of data
70          final byte[] rawData = new byte[1048576];
71          for (int i = 0; i < rawData.length; ++i) {
72              rawData[i] = (byte) Math.floor(Math.random() * 256);
73          }
74  
75          // Compress it
76          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
77          try (BZip2CompressorOutputStream bzipOut = new BZip2CompressorOutputStream(baos)) {
78              bzipOut.write(rawData);
79              bzipOut.flush();
80              bzipOut.close();
81              baos.flush();
82          }
83  
84          // Try to read it back in
85          final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
86          try (BZip2CompressorInputStream bzipIn = new BZip2CompressorInputStream(bais)) {
87              final byte[] buffer = new byte[1024];
88              assertEquals(1024, bzipIn.read(buffer, 0, 1024));
89              assertEquals(0, bzipIn.read(buffer, 1024, 0));
90              assertEquals(1024, bzipIn.read(buffer, 0, 1024));
91          }
92      }
93  
94      @Test
95      public void testShouldThrowAnIOExceptionWhenAppliedToAZipFile() throws Exception {
96          try (InputStream in = newInputStream("bla.zip")) {
97              assertThrows(IOException.class, () -> new BZip2CompressorInputStream(in));
98          }
99      }
100 
101     /**
102      * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-516">COMPRESS-516</a>
103      */
104     @Test
105     public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS516() {
106         assertThrows(IOException.class,
107                 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
108                         0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
109                         0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
110                         0x68, 0x34, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x62, 0xe4, 0x4f, 0x51, 0x00, 0x00, 0x0d, 0xd1, 0x80, 0x00, 0x10, 0x40, 0x00, 0x35,
111                         0xf9, 0x8b, 0x00, 0x20, 0x00, 0x48, 0x89, 0xfa, 0x94, 0xf2, 0x9e, 0x29, 0xe8, 0xd2, 0x11, 0x8a, 0x4f, 0x53, 0x34, 0x0f, 0x51, 0x7a,
112                         0xed, 0x86, 0x65, 0xd6, 0xed, 0x61, 0xee, 0x68, 0x89, 0x48, 0x7d, 0x07, 0x71, 0x92, 0x2a, 0x50, 0x60, 0x04, 0x95, 0x61, 0x35, 0x47,
113                         0x73, 0x31, 0x29, 0xc2, 0xdd, 0x5e, 0xc7, 0x4a, 0x15, 0x14, 0x32, 0x4c, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }));
114     }
115 
116     /**
117      * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-519">COMPRESS-519</a>
118      */
119     @Test
120     public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS519() {
121         assertThrows(IOException.class,
122                 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x63,
123                         0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
124                         0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
125                         0x68, 0x34, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x62, 0xe4, 0x4f, 0x51, 0x80, 0x00, 0x0d, 0xd1, 0x80, 0x00, 0x10, 0x40, 0x00, 0x35,
126                         0xf9, 0x8b, 0x00, 0x20, 0x00, 0x48, 0x89, 0xfa, 0x94, 0xf2, 0x9e, 0x29, 0xe8, 0xd2, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x50, 0x4b,
127                         0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }));
128     }
129 
130     @Test
131     public void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws IOException {
132         final File input = getFile("bla.txt.bz2");
133         try (InputStream is = Files.newInputStream(input.toPath());
134                 BZip2CompressorInputStream in = new BZip2CompressorInputStream(is)) {
135             IOUtils.toByteArray(in);
136             assertEquals(-1, in.read());
137             assertEquals(-1, in.read());
138         }
139     }
140 }