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.bzip2;
20
21 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23
24 import java.io.BufferedInputStream;
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.nio.ByteBuffer;
30 import java.nio.channels.Channels;
31 import java.nio.channels.ReadableByteChannel;
32 import java.util.Arrays;
33
34 import org.junit.jupiter.api.AfterEach;
35 import org.junit.jupiter.api.BeforeAll;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38
39
40
41
42
43
44 public class PythonTruncatedBzip2Test {
45
46
47 private static final String TEXT = "root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:\ndaemon:x:2:2:daemon:/sbin:\nadm:x:3:4:adm:/var/adm:\nlp:x:4:7:"
48 + "lp:/var/spool/lpd:\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8"
49 + ":12:mail:/var/spool/mail:\nnews:x:9:13:news:/var/spool/news:\nuucp:x:10:14:uucp:/var/spool/uucp:\noperator:x:11:0:operator:/root:\ngames:x:12"
50 + ":100:games:/usr/games:\ngopher:x:13:30:gopher:/usr/lib/gopher-data:\nftp:x:14:50:FTP User:/var/ftp:/bin/bash\nnobody:x:65534:65534:Nobody:"
51 + "/home:\npostfix:x:100:101:postfix:/var/spool/postfix:\nniemeyer:x:500:500::/home/niemeyer:/bin/bash\npostgres:x:101:102:PostgreSQL Server:"
52 + "/var/lib/pgsql:/bin/bash\nmysql:x:102:103:MySQL server:/var/lib/mysql:/bin/bash\nwww:x:103:104::/var/www:/bin/false\n";
53
54
55 private static byte[] DATA;
56 private static byte[] TRUNCATED_DATA;
57
58 @BeforeAll
59 public static void initializeTestData() throws IOException {
60 final ByteArrayOutputStream out = new ByteArrayOutputStream();
61 try (BZip2CompressorOutputStream bz2out = new BZip2CompressorOutputStream(out)) {
62 bz2out.write(TEXT.getBytes(), 0, TEXT.getBytes().length);
63 }
64 DATA = out.toByteArray();
65
66
67 TRUNCATED_DATA = Arrays.copyOfRange(DATA, 0, DATA.length - 10);
68 }
69
70 @SuppressWarnings("resource")
71 private static ReadableByteChannel makeBZ2C(final InputStream source) throws IOException {
72 final BufferedInputStream bin = new BufferedInputStream(source);
73 final BZip2CompressorInputStream bZin = new BZip2CompressorInputStream(bin, true);
74 return Channels.newChannel(bZin);
75 }
76
77 private ReadableByteChannel bz2Channel;
78
79 @AfterEach
80 public void closeChannel() throws IOException {
81 bz2Channel.close();
82 bz2Channel = null;
83 }
84
85 @BeforeEach
86 public void initializeChannel() throws IOException {
87 this.bz2Channel = makeBZ2C(new ByteArrayInputStream(TRUNCATED_DATA));
88 }
89
90 @Test
91 public void testPartialReadTruncatedData() throws IOException {
92
93
94
95
96 final int length = TEXT.length();
97 final ByteBuffer buffer1 = ByteBuffer.allocate(length);
98 bz2Channel.read(buffer1);
99
100 assertArrayEquals(Arrays.copyOfRange(TEXT.getBytes(), 0, length), buffer1.array());
101
102
103 final ByteBuffer buffer2 = ByteBuffer.allocate(1);
104 assertThrows(IOException.class, () -> bz2Channel.read(buffer2), "The read should have thrown.");
105 }
106
107 @Test
108 public void testTruncatedData() {
109
110
111 final ByteBuffer buffer = ByteBuffer.allocate(8192);
112 assertThrows(IOException.class, () -> bz2Channel.read(buffer));
113 }
114 }