1 /* 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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 30 import java.util.*; 31 import java.util.zip.*; 32 import java.io.*; 33 import static java.lang.System.*; 34 import static java.util.zip.ZipFile.*; 35 36 public 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 try (FileOutputStream fos = new FileOutputStream("x.zip"); 51 ZipOutputStream zos = new ZipOutputStream(fos)) 52 { 53 ZipEntry e = new ZipEntry("x"); 54 zos.putNextEntry(e); 55 zos.write((int)'x'); 56 } 57 58 int len = (int)(new File("x.zip").length()); 59 byte[] good = new byte[len]; 60 try (FileInputStream fis = new FileInputStream("x.zip")) { 61 fis.read(good); 62 } 63 new File("x.zip").delete(); 64 65 int endpos = len - ENDHDR; 66 int cenpos = u16(good, endpos+ENDOFF); 67 int locpos = u16(good, cenpos+CENOFF); 68 if (u32(good, endpos) != ENDSIG) fail("Where's ENDSIG?"); 69 if (u32(good, cenpos) != CENSIG) fail("Where's CENSIG?"); 70 if (u32(good, locpos) != LOCSIG) fail("Where's LOCSIG?"); 71 if (u16(good, locpos+LOCNAM) != u16(good,cenpos+CENNAM)) 72 fail("Name field length mismatch"); 73 if (u16(good, locpos+LOCEXT) != u16(good,cenpos+CENEXT)) 74 fail("Extra field length mismatch"); 75 76 byte[] bad; 77 78 err.println("corrupted ENDSIZ"); 79 bad = good.clone(); 80 bad[endpos+ENDSIZ]=(byte)0xff; 81 checkZipException(bad, ".*bad central directory size.*"); 82 83 err.println("corrupted ENDOFF"); 84 bad = good.clone(); 85 bad[endpos+ENDOFF]=(byte)0xff; 86 checkZipException(bad, ".*bad central directory offset.*"); 87 88 err.println("corrupted CENSIG"); 89 bad = good.clone(); 90 bad[cenpos]++; 91 checkZipException(bad, ".*bad signature.*"); 92 93 err.println("corrupted CENFLG"); 94 bad = good.clone(); 95 bad[cenpos+CENFLG] |= 1; 96 checkZipException(bad, ".*encrypted entry.*"); 97 98 err.println("corrupted CENNAM 1"); 99 bad = good.clone(); 100 bad[cenpos+CENNAM]++; 101 checkZipException(bad, ".*bad header size.*"); 102 103 err.println("corrupted CENNAM 2"); 104 bad = good.clone(); 105 bad[cenpos+CENNAM]--; 106 checkZipException(bad, ".*bad header size.*"); 107 108 err.println("corrupted CENNAM 3"); 109 bad = good.clone(); 110 bad[cenpos+CENNAM] = (byte)0xfd; 111 bad[cenpos+CENNAM+1] = (byte)0xfd; 112 checkZipException(bad, ".*bad header size.*"); 113 114 err.println("corrupted CENEXT 1"); 115 bad = good.clone(); 116 bad[cenpos+CENEXT]++; 117 checkZipException(bad, ".*bad header size.*"); 118 119 err.println("corrupted CENEXT 2"); 120 bad = good.clone(); 121 bad[cenpos+CENEXT] = (byte)0xfd; 122 bad[cenpos+CENEXT+1] = (byte)0xfd; 123 checkZipException(bad, ".*bad header size.*"); 124 125 err.println("corrupted CENCOM"); 126 bad = good.clone(); 127 bad[cenpos+CENCOM]++; 128 checkZipException(bad, ".*bad header size.*"); 129 130 err.println("corrupted CENHOW"); 131 bad = good.clone(); 132 bad[cenpos+CENHOW] = 2; 133 checkZipException(bad, ".*bad compression method.*"); 134 135 err.println("corrupted LOCSIG"); 136 bad = good.clone(); 137 bad[locpos]++; 138 checkZipExceptionInGetInputStream(bad, ".*bad signature.*"); 139 140 out.printf("passed = %d, failed = %d%n", passed, failed); 141 if (failed > 0) throw new Exception("Some tests failed"); 142 } 143 144 static int uniquifier = 432; 145 146 static void checkZipExceptionImpl(byte[] data, 147 String msgPattern, 148 boolean getInputStream) { 149 String zipName = "bad" + (uniquifier++) + ".zip"; 150 try { 151 try (FileOutputStream fos = new FileOutputStream(zipName)) { 152 fos.write(data); 153 } 154 try (ZipFile zf = new ZipFile(zipName)) { 155 if (getInputStream) { 156 InputStream is = zf.getInputStream(new ZipEntry("x")); 157 is.read(); 158 } 159 } 160 fail("Failed to throw expected ZipException"); 161 } catch (ZipException e) { 162 if (e.getMessage().matches(msgPattern)) 163 passed++; 164 else 165 unexpected(e); 166 } catch (Throwable t) { 167 unexpected(t); 168 } finally { 169 new File(zipName).delete(); 170 } 171 } 172 173 static void checkZipException(byte[] data, String msgPattern) { 174 checkZipExceptionImpl(data, msgPattern, false); 175 } 176 177 static void checkZipExceptionInGetInputStream(byte[] data, String msgPattern) { 178 checkZipExceptionImpl(data, msgPattern, true); 179 } 180 181 static int u8(byte[] data, int offset) { 182 return data[offset]&0xff; 183 } 184 185 static int u16(byte[] data, int offset) { 186 return u8(data,offset) + (u8(data,offset+1)<<8); 187 } 188 189 static int u32(byte[] data, int offset) { 190 return u16(data,offset) + (u16(data,offset+2)<<16); 191 } 192 193 // The following can be deleted once this bug is fixed: 194 // 6225935: "import static" accessibility rules for symbols different for no reason 195 static final long LOCSIG = ZipFile.LOCSIG; 196 static final long EXTSIG = ZipFile.EXTSIG; 197 static final long CENSIG = ZipFile.CENSIG; 198 static final long ENDSIG = ZipFile.ENDSIG; 199 200 static final int LOCHDR = ZipFile.LOCHDR; 201 static final int EXTHDR = ZipFile.EXTHDR; 202 static final int CENHDR = ZipFile.CENHDR; 203 static final int ENDHDR = ZipFile.ENDHDR; 204 205 static final int LOCVER = ZipFile.LOCVER; 206 static final int LOCFLG = ZipFile.LOCFLG; 207 static final int LOCHOW = ZipFile.LOCHOW; 208 static final int LOCTIM = ZipFile.LOCTIM; 209 static final int LOCCRC = ZipFile.LOCCRC; 210 static final int LOCSIZ = ZipFile.LOCSIZ; 211 static final int LOCLEN = ZipFile.LOCLEN; 212 static final int LOCNAM = ZipFile.LOCNAM; 213 static final int LOCEXT = ZipFile.LOCEXT; 214 215 static final int CENVEM = ZipFile.CENVEM; 216 static final int CENVER = ZipFile.CENVER; 217 static final int CENFLG = ZipFile.CENFLG; 218 static final int CENHOW = ZipFile.CENHOW; 219 static final int CENTIM = ZipFile.CENTIM; 220 static final int CENCRC = ZipFile.CENCRC; 221 static final int CENSIZ = ZipFile.CENSIZ; 222 static final int CENLEN = ZipFile.CENLEN; 223 static final int CENNAM = ZipFile.CENNAM; 224 static final int CENEXT = ZipFile.CENEXT; 225 static final int CENCOM = ZipFile.CENCOM; 226 static final int CENDSK = ZipFile.CENDSK; 227 static final int CENATT = ZipFile.CENATT; 228 static final int CENATX = ZipFile.CENATX; 229 static final int CENOFF = ZipFile.CENOFF; 230 231 static final int ENDSUB = ZipFile.ENDSUB; 232 static final int ENDTOT = ZipFile.ENDTOT; 233 static final int ENDSIZ = ZipFile.ENDSIZ; 234 static final int ENDOFF = ZipFile.ENDOFF; 235 static final int ENDCOM = ZipFile.ENDCOM; 236 }