1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.compressors.deflate64;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNull;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.mockito.Mockito.times;
23
24 import java.io.BufferedReader;
25 import java.io.ByteArrayInputStream;
26 import java.io.EOFException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30
31 import org.apache.commons.compress.archivers.ArchiveException;
32 import org.apache.commons.compress.archivers.ArchiveInputStream;
33 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
34 import org.apache.commons.compress.compressors.CompressorStreamFactory;
35 import org.apache.commons.io.IOUtils;
36 import org.junit.jupiter.api.Test;
37 import org.junit.jupiter.api.extension.ExtendWith;
38 import org.mockito.Mock;
39 import org.mockito.Mockito;
40 import org.mockito.junit.jupiter.MockitoExtension;
41
42 @ExtendWith(MockitoExtension.class)
43 public class Deflate64CompressorInputStreamTest {
44 private final HuffmanDecoder nullDecoder = null;
45
46 @Mock
47 private HuffmanDecoder decoder;
48
49 private void fuzzingTest(final int[] bytes) throws IOException, ArchiveException {
50 final int len = bytes.length;
51 final byte[] input = new byte[len];
52 for (int i = 0; i < len; i++) {
53 input[i] = (byte) bytes[i];
54 }
55 try (ArchiveInputStream<?> ais = ArchiveStreamFactory.DEFAULT.createArchiveInputStream("zip", new ByteArrayInputStream(input))) {
56 ais.getNextEntry();
57 IOUtils.toByteArray(ais);
58 }
59 }
60
61 @Test
62 public void testCloseCallsDecoder() throws Exception {
63
64 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder)) {
65
66 }
67
68 Mockito.verify(decoder, times(1)).close();
69 }
70
71 @Test
72 public void testCloseIsDelegatedJustOnce() throws Exception {
73
74 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder)) {
75 input.close();
76 }
77
78 Mockito.verify(decoder, times(1)).close();
79 }
80
81 @Test
82 public void testDelegatesAvailable() throws Exception {
83 Mockito.when(decoder.available()).thenReturn(1024);
84
85 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder)) {
86 assertEquals(1024, input.available());
87 }
88 }
89
90 @Test
91 public void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws Exception {
92 final byte[] buf = new byte[2];
93 try (Deflate64CompressorInputStream in = new Deflate64CompressorInputStream(nullDecoder)) {
94 IOUtils.toByteArray(in);
95 assertEquals(-1, in.read(buf));
96 assertEquals(-1, in.read(buf));
97 }
98 }
99
100 @Test
101 public void testProperSizeWhenClosed() throws Exception {
102 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(nullDecoder)) {
103 assertEquals(0, input.available());
104 }
105 }
106
107 @Test
108 public void testReadWhenClosed() throws Exception {
109 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(nullDecoder)) {
110 assertEquals(-1, input.read());
111 assertEquals(-1, input.read(new byte[1]));
112 assertEquals(-1, input.read(new byte[1], 0, 1));
113 }
114 }
115
116
117
118
119 @Test
120 public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS521() {
121 assertThrows(IOException.class,
122 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x2e, 0x00, 0xb6, 0x00, 0x09, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0x00, 0xfe, 0x77, 0x63,
123 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x0c, 0x00, 0x03, 0xe7, 0xce, 0x64,
124 0x55, 0xf3, 0xce, 0x65, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x42, 0x5a,
125 0x68, 0x34 }));
126 }
127
128
129
130
131 @Test
132 public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS522() {
133 assertThrows(IOException.class,
134 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x4a, 0x84, 0x02, 0x40, 0x00, 0x01, 0x00, 0xff, 0xff }));
136 }
137
138
139
140
141 @Test
142 public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS525() {
143 assertThrows(IOException.class, () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x00, 0x61, 0x4a, 0x04, 0x04, 0x00, 0x00, 0xff, 0xff, 0x50,
145 0x53, 0x07, 0x08, 0x43, 0xbe, 0xb7, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x4a, 0x02,
147 0x04, 0x00, 0x00, 0xff, 0xff, 0x50, 0x4b, 0x7f, 0x08, 0xf9, 0xef, 0xbe, 0x71, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x03,
148 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
149 0x00, 0x00, 0x00, 0x63, 0x4a, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0x6f, 0xdf }));
150 }
151
152
153
154
155 @Test
156 public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS526() {
157 assertThrows(IOException.class,
158 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x61, 0x4a, 0x04, 0x04, 0x00, 0x00, 0xff, 0xff, 0x50, 0x53, 0x07,
160 0x08, 0x43, 0xbe, 0xb7, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62,
162 0x4a, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x50, 0x4b, 0x7f, 0x08, 0xf9, 0xef, 0xbe, 0x71, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
163 0x00, 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x4a, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0x01,
165 0xdf, 0xb9, 0x06, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 0x08 }));
166 }
167
168
169
170
171 @Test
172 public void testShouldThrowIOExceptionInsteadOfRuntimeExceptionCOMPRESS527() {
173 assertThrows(IOException.class,
174 () -> fuzzingTest(new int[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x84, 0xb6, 0xba, 0x46, 0x72, 0xb6, 0xfe, 0x77, 0x4a,
175 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x62, 0x62, 0x62, 0x55, 0x54, 0x09, 0x00, 0x03, 0xe7, 0xce, 0x64,
176 0x55, 0xf3, 0xce, 0x64, 0x55, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x5c, 0xf9, 0x01, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x1d, 0x8b,
177 0xc1, 0x0d, 0xc0, 0x30, 0x08, 0x03, 0xff, 0x99, 0xc2, 0xab, 0x81, 0x50, 0x1a, 0xa8, 0x44, 0x1e, 0x56, 0x30, 0x7f, 0x21, 0x1f, 0x5b,
178 0x3e, 0x9d, 0x85, 0x6e }));
179 }
180
181 @Test
182 public void testShouldThrowsEOFExceptionOnTruncatedStreams() throws IOException {
183 final byte[] data = { 1, 11, 0, -12, -1, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', };
184
185 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(new ByteArrayInputStream(data));
186 BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
187 assertThrows(EOFException.class, () -> br.readLine());
188 }
189 }
190
191 @Test
192 public void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws Exception {
193 try (Deflate64CompressorInputStream in = new Deflate64CompressorInputStream(nullDecoder)) {
194 IOUtils.toByteArray(in);
195 assertEquals(-1, in.read());
196 assertEquals(-1, in.read());
197 }
198 }
199
200 @Test
201 public void testStreamIgnoresExtraBytesAfterDeflatedInput() throws Exception {
202 final byte[] data = { 1, 11, 0, -12, -1, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 'X' };
203
204 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(new ByteArrayInputStream(data));
205 BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
206 assertEquals("Hello World", br.readLine());
207 assertNull(br.readLine());
208 }
209 }
210
211 @Test
212 public void testUncompressedBlock() throws Exception {
213 final byte[] data = { 1, 11, 0, -12, -1, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
214
215 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(new ByteArrayInputStream(data));
216 BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
217 assertEquals("Hello World", br.readLine());
218 assertNull(br.readLine());
219 }
220 }
221
222 @Test
223 public void testUncompressedBlockAvailable() throws Exception {
224 final byte[] data = { 1, 11, 0, -12, -1, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
225
226 try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(new ByteArrayInputStream(data))) {
227 assertEquals('H', input.read());
228 assertEquals(10, input.available());
229 }
230 }
231
232 @Test
233 public void testUncompressedBlockViaFactory() throws Exception {
234 final byte[] data = { 1, 11, 0, -12, -1, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
235
236 try (InputStream input = new CompressorStreamFactory().createCompressorInputStream(CompressorStreamFactory.DEFLATE64, new ByteArrayInputStream(data));
237 BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
238 assertEquals("Hello World", br.readLine());
239 assertNull(br.readLine());
240 }
241 }
242 }