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