blob: 4efe39b69a2c7d7bdf29e9161f5088a57ebb6deb [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/* @test
25 * @bug 4770745 6218846 6218848 6237956
26 * @summary test for correct detection and reporting of corrupted zip files
27 * @author Martin Buchholz
28 */
29
30import java.util.*;
31import java.util.zip.*;
32import java.io.*;
33import static java.lang.System.*;
34import static java.util.zip.ZipFile.*;
35
36public class CorruptedZipFiles {
37 static int passed = 0, failed = 0;
38
39 static void fail(String msg) {
40 failed++;
41 err.println(msg);
42 }
43
44 static void unexpected(Throwable t) {
45 failed++;
46 t.printStackTrace();
47 }
48
49 public static void main(String[] args) throws Exception {
50 ZipOutputStream zos = new ZipOutputStream(
51 new FileOutputStream("x.zip"));
52 ZipEntry e = new ZipEntry("x");
53 zos.putNextEntry(e);
54 zos.write((int)'x');
55 zos.close();
56 zos = null;
57
58 int len = (int)(new File("x.zip").length());
59 byte[] good = new byte[len];
60 FileInputStream fis = new FileInputStream("x.zip");
61 fis.read(good);
62 fis.close();
63 fis = null;
64 new File("x.zip").delete();
65
66 int endpos = len - ENDHDR;
67 int cenpos = u16(good, endpos+ENDOFF);
68 int locpos = u16(good, cenpos+CENOFF);
69 if (u32(good, endpos) != ENDSIG) fail("Where's ENDSIG?");
70 if (u32(good, cenpos) != CENSIG) fail("Where's CENSIG?");
71 if (u32(good, locpos) != LOCSIG) fail("Where's LOCSIG?");
72 if (u16(good, locpos+LOCNAM) != u16(good,cenpos+CENNAM))
73 fail("Name field length mismatch");
74 if (u16(good, locpos+LOCEXT) != u16(good,cenpos+CENEXT))
75 fail("Extra field length mismatch");
76
77 byte[] bad;
78
79 err.println("corrupted ENDSIZ");
80 bad = good.clone();
81 bad[endpos+ENDSIZ]=(byte)0xff;
82 checkZipException(bad, ".*bad central directory size.*");
83
84 err.println("corrupted ENDOFF");
85 bad = good.clone();
86 bad[endpos+ENDOFF]=(byte)0xff;
87 checkZipException(bad, ".*bad central directory offset.*");
88
89 err.println("corrupted CENSIG");
90 bad = good.clone();
91 bad[cenpos]++;
92 checkZipException(bad, ".*bad signature.*");
93
94 err.println("corrupted CENFLG");
95 bad = good.clone();
96 bad[cenpos+CENFLG] |= 1;
97 checkZipException(bad, ".*encrypted entry.*");
98
99 err.println("corrupted CENNAM 1");
100 bad = good.clone();
101 bad[cenpos+CENNAM]++;
102 checkZipException(bad, ".*bad header size.*");
103
104 err.println("corrupted CENNAM 2");
105 bad = good.clone();
106 bad[cenpos+CENNAM]--;
107 checkZipException(bad, ".*bad header size.*");
108
109 err.println("corrupted CENNAM 3");
110 bad = good.clone();
111 bad[cenpos+CENNAM] = (byte)0xfd;
112 bad[cenpos+CENNAM+1] = (byte)0xfd;
113 checkZipException(bad, ".*bad header size.*");
114
115 err.println("corrupted CENEXT 1");
116 bad = good.clone();
117 bad[cenpos+CENEXT]++;
118 checkZipException(bad, ".*bad header size.*");
119
120 err.println("corrupted CENEXT 2");
121 bad = good.clone();
122 bad[cenpos+CENEXT] = (byte)0xfd;
123 bad[cenpos+CENEXT+1] = (byte)0xfd;
124 checkZipException(bad, ".*bad header size.*");
125
126 err.println("corrupted CENCOM");
127 bad = good.clone();
128 bad[cenpos+CENCOM]++;
129 checkZipException(bad, ".*bad header size.*");
130
131 err.println("corrupted CENHOW");
132 bad = good.clone();
133 bad[cenpos+CENHOW] = 2;
134 checkZipException(bad, ".*bad compression method.*");
135
136 err.println("corrupted LOCSIG");
137 bad = good.clone();
138 bad[locpos]++;
139 checkZipExceptionInGetInputStream(bad, ".*bad signature.*");
140
141 out.printf("passed = %d, failed = %d%n", passed, failed);
142 if (failed > 0) throw new Exception("Some tests failed");
143 }
144
145 static int uniquifier = 432;
146
147 static void checkZipExceptionImpl(byte[] data,
148 String msgPattern,
149 boolean getInputStream) {
150 String zipName = "bad" + (uniquifier++) + ".zip";
151 try {
152 FileOutputStream fos = new FileOutputStream(zipName);
153 fos.write(data);
154 fos.close();
155 ZipFile zf = new ZipFile(zipName);
156 if (getInputStream) {
157 InputStream is = zf.getInputStream(new ZipEntry("x"));
158 is.read();
159 }
160 fail("Failed to throw expected ZipException");
161 zf.close();
162 } catch (ZipException e) {
163 if (e.getMessage().matches(msgPattern))
164 passed++;
165 else
166 unexpected(e);
167 } catch (Throwable t) {
168 unexpected(t);
169 }
170 finally {
171 new File(zipName).delete();
172 }
173 }
174
175 static void checkZipException(byte[] data, String msgPattern) {
176 checkZipExceptionImpl(data, msgPattern, false);
177 }
178
179 static void checkZipExceptionInGetInputStream(byte[] data, String msgPattern) {
180 checkZipExceptionImpl(data, msgPattern, true);
181 }
182
183 static int u8(byte[] data, int offset) {
184 return data[offset]&0xff;
185 }
186
187 static int u16(byte[] data, int offset) {
188 return u8(data,offset) + (u8(data,offset+1)<<8);
189 }
190
191 static int u32(byte[] data, int offset) {
192 return u16(data,offset) + (u16(data,offset+2)<<16);
193 }
194
195 // The following can be deleted once this bug is fixed:
196 // 6225935: "import static" accessibility rules for symbols different for no reason
197 static final long LOCSIG = ZipFile.LOCSIG;
198 static final long EXTSIG = ZipFile.EXTSIG;
199 static final long CENSIG = ZipFile.CENSIG;
200 static final long ENDSIG = ZipFile.ENDSIG;
201
202 static final int LOCHDR = ZipFile.LOCHDR;
203 static final int EXTHDR = ZipFile.EXTHDR;
204 static final int CENHDR = ZipFile.CENHDR;
205 static final int ENDHDR = ZipFile.ENDHDR;
206
207 static final int LOCVER = ZipFile.LOCVER;
208 static final int LOCFLG = ZipFile.LOCFLG;
209 static final int LOCHOW = ZipFile.LOCHOW;
210 static final int LOCTIM = ZipFile.LOCTIM;
211 static final int LOCCRC = ZipFile.LOCCRC;
212 static final int LOCSIZ = ZipFile.LOCSIZ;
213 static final int LOCLEN = ZipFile.LOCLEN;
214 static final int LOCNAM = ZipFile.LOCNAM;
215 static final int LOCEXT = ZipFile.LOCEXT;
216
217 static final int CENVEM = ZipFile.CENVEM;
218 static final int CENVER = ZipFile.CENVER;
219 static final int CENFLG = ZipFile.CENFLG;
220 static final int CENHOW = ZipFile.CENHOW;
221 static final int CENTIM = ZipFile.CENTIM;
222 static final int CENCRC = ZipFile.CENCRC;
223 static final int CENSIZ = ZipFile.CENSIZ;
224 static final int CENLEN = ZipFile.CENLEN;
225 static final int CENNAM = ZipFile.CENNAM;
226 static final int CENEXT = ZipFile.CENEXT;
227 static final int CENCOM = ZipFile.CENCOM;
228 static final int CENDSK = ZipFile.CENDSK;
229 static final int CENATT = ZipFile.CENATT;
230 static final int CENATX = ZipFile.CENATX;
231 static final int CENOFF = ZipFile.CENOFF;
232
233 static final int ENDSUB = ZipFile.ENDSUB;
234 static final int ENDTOT = ZipFile.ENDTOT;
235 static final int ENDSIZ = ZipFile.ENDSIZ;
236 static final int ENDOFF = ZipFile.ENDOFF;
237 static final int ENDCOM = ZipFile.ENDCOM;
238}