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