1/* 2 * Copyright (c) 2009, 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/* 25 * Borrowing significantly from Martin Buchholz's CorruptedZipFiles.java 26 * 27 * Needed a way of testing the checks for corrupt zip/jar entry in 28 * inflate_file from file j2se/src/share/bin/parse_manifest.c 29 * and running them with the 64-bit launcher. e.g. 30 * sparcv9/bin/java -jar badjar.jar 31 * 32 * Run from a script driver Test6842838.sh as we want to specifically run 33 * bin/sparcv9/java, the 64-bit launcher. 34 * 35 * So this program will create a zip file and damage it in the way 36 * required to tickle this bug. 37 * 38 * It will cause a buffer overrun: but that will not always crash. 39 * Use libumem preloaded by the script driver in order to 40 * abort quickly when the overrun happens. That makes the test 41 * Solaris-specific. 42 */ 43 44import java.util.*; 45import java.util.zip.*; 46import java.io.*; 47import static java.lang.System.*; 48import static java.util.zip.ZipFile.*; 49 50public class CreateBadJar { 51 52public static void main(String [] arguments) { 53 54 if (arguments.length != 2) { 55 throw new RuntimeException("Arguments: jarfilename entryname"); 56 } 57 String outFile = arguments[0]; 58 String entryName = arguments[1]; 59 60 try { 61 // If the named file doesn't exist, create it. 62 // If it does, we are expecting it to contain the named entry, for 63 // alteration. 64 if (!new File(outFile).exists()) { 65 System.out.println("Creating file " + outFile); 66 67 // Create the requested zip/jar file. 68 ZipOutputStream zos = null; 69 zos = new ZipOutputStream( 70 new FileOutputStream(outFile)); 71 72 ZipEntry e = new ZipEntry(entryName); 73 zos.putNextEntry(e); 74 for (int j=0; j<50000; j++) { 75 zos.write((int)'a'); 76 } 77 zos.closeEntry(); 78 zos.close(); 79 zos = null; 80 } 81 82 // Read it. 83 int len = (int)(new File(outFile).length()); 84 byte[] good = new byte[len]; 85 FileInputStream fis = new FileInputStream(outFile); 86 fis.read(good); 87 fis.close(); 88 fis = null; 89 90 int endpos = len - ENDHDR; 91 int cenpos = u16(good, endpos+ENDOFF); 92 if (u32(good, cenpos) != CENSIG) throw new RuntimeException("Where's CENSIG?"); 93 94 byte[] bad; 95 bad = good.clone(); 96 97 // Corrupt it... 98 int pos = findInCEN(bad, cenpos, entryName); 99 100 // What bad stuff are we doing to it? 101 // Store a 32-bit -1 in uncomp size. 102 bad[pos+0x18]=(byte)0xff; 103 bad[pos+0x19]=(byte)0xff; 104 bad[pos+0x1a]=(byte)0xff; 105 bad[pos+0x1b]=(byte)0xff; 106 107 // Bad work complete, delete the original. 108 new File(outFile).delete(); 109 110 // Write it. 111 FileOutputStream fos = new FileOutputStream(outFile); 112 fos.write(bad); 113 fos.close(); 114 fos = null; 115 116 } catch (Exception e) { 117 e.printStackTrace(); 118 } 119 120} 121 122 /* 123 * Scan Central Directory File Headers looking for the named entry. 124 */ 125 126 static int findInCEN(byte[] bytes, int cenpos, String entryName) { 127 int pos = cenpos; 128 int nextPos = 0; 129 String filename = null; 130 do { 131 if (nextPos != 0) { 132 pos = nextPos; 133 } 134 System.out.println("entry at pos = " + pos); 135 if (u32(bytes, pos) != CENSIG) throw new RuntimeException ("entry not found in CEN or premature end..."); 136 137 int csize = u32(bytes, pos+0x14); // +0x14 1 dword csize 138 int uncompsize = u32(bytes, pos+0x18); // +0x18 1 dword uncomp size 139 int filenameLength = u16(bytes, pos+0x1c); // +0x1c 1 word length of filename 140 int extraLength = u16(bytes, pos+0x1e); // +0x1e 1 world length of extra field 141 int commentLength = u16(bytes, pos+0x20); // +0x20 1 world length of file comment 142 filename = new String(bytes, pos+0x2e, filenameLength); // +0x2e chars of filename 143 int offset = u32(bytes, pos+0x2a); // +0x2a chars of filename 144 145 System.out.println("filename = " + filename + "\ncsize = " + csize + 146 " uncomp.size = " + uncompsize +" file offset = " + offset); 147 nextPos = pos + 0x2e + filenameLength + extraLength + commentLength; 148 149 } while (!filename.equals(entryName)); 150 151 System.out.println("entry found at pos = " + pos); 152 return pos; 153 } 154 155 static int u8(byte[] data, int offset) { 156 return data[offset]&0xff; 157 } 158 159 static int u16(byte[] data, int offset) { 160 return u8(data,offset) + (u8(data,offset+1)<<8); 161 } 162 163 static int u32(byte[] data, int offset) { 164 return u16(data,offset) + (u16(data,offset+2)<<16); 165 } 166 167} 168 169