6842838: 64-bit failure in handling invalid manifest in launcher.
Summary: Don't compare with hard-coded 32-bit -1 when checking zip fields.
Reviewed-by: ksrini
--- a/jdk/src/share/bin/parse_manifest.c Mon Sep 14 17:47:26 2009 +0100
+++ b/jdk/src/share/bin/parse_manifest.c Mon Sep 14 20:55:08 2009 +0100
@@ -59,7 +59,7 @@
char *out;
z_stream zs;
- if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+ if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
return (NULL);
if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
return (NULL);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/CreateBadJar.java Mon Sep 14 20:55:08 2009 +0100
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * Borrowing significantly from Martin Buchholz's CorruptedZipFiles.java
+ *
+ * Needed a way of testing the checks for corrupt zip/jar entry in
+ * inflate_file from file j2se/src/share/bin/parse_manifest.c
+ * and running them with the 64-bit launcher. e.g.
+ * sparcv9/bin/java -jar badjar.jar
+ *
+ * Run from a script driver Test6842838.sh as we want to specifically run
+ * bin/sparcv9/java, the 64-bit launcher.
+ *
+ * So this program will create a zip file and damage it in the way
+ * required to tickle this bug.
+ *
+ * It will cause a buffer overrun: but that will not always crash.
+ * Use libumem preloaded by the script driver in order to
+ * abort quickly when the overrun happens. That makes the test
+ * Solaris-specific.
+ */
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import static java.lang.System.*;
+import static java.util.zip.ZipFile.*;
+
+public class CreateBadJar {
+
+public static void main(String [] arguments) {
+
+ if (arguments.length != 2) {
+ throw new RuntimeException("Arguments: jarfilename entryname");
+ }
+ String outFile = arguments[0];
+ String entryName = arguments[1];
+
+ try {
+ // If the named file doesn't exist, create it.
+ // If it does, we are expecting it to contain the named entry, for
+ // alteration.
+ if (!new File(outFile).exists()) {
+ System.out.println("Creating file " + outFile);
+
+ // Create the requested zip/jar file.
+ ZipOutputStream zos = null;
+ zos = new ZipOutputStream(
+ new FileOutputStream(outFile));
+
+ ZipEntry e = new ZipEntry(entryName);
+ zos.putNextEntry(e);
+ for (int j=0; j<50000; j++) {
+ zos.write((int)'a');
+ }
+ zos.closeEntry();
+ zos.close();
+ zos = null;
+ }
+
+ // Read it.
+ int len = (int)(new File(outFile).length());
+ byte[] good = new byte[len];
+ FileInputStream fis = new FileInputStream(outFile);
+ fis.read(good);
+ fis.close();
+ fis = null;
+
+ int endpos = len - ENDHDR;
+ int cenpos = u16(good, endpos+ENDOFF);
+ if (u32(good, cenpos) != CENSIG) throw new RuntimeException("Where's CENSIG?");
+
+ byte[] bad;
+ bad = good.clone();
+
+ // Corrupt it...
+ int pos = findInCEN(bad, cenpos, entryName);
+
+ // What bad stuff are we doing to it?
+ // Store a 32-bit -1 in uncomp size.
+ bad[pos+0x18]=(byte)0xff;
+ bad[pos+0x19]=(byte)0xff;
+ bad[pos+0x1a]=(byte)0xff;
+ bad[pos+0x1b]=(byte)0xff;
+
+ // Bad work complete, delete the original.
+ new File(outFile).delete();
+
+ // Write it.
+ FileOutputStream fos = new FileOutputStream(outFile);
+ fos.write(bad);
+ fos.close();
+ fos = null;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+}
+
+ /*
+ * Scan Central Directory File Headers looking for the named entry.
+ */
+
+ static int findInCEN(byte[] bytes, int cenpos, String entryName) {
+ int pos = cenpos;
+ int nextPos = 0;
+ String filename = null;
+ do {
+ if (nextPos != 0) {
+ pos = nextPos;
+ }
+ System.out.println("entry at pos = " + pos);
+ if (u32(bytes, pos) != CENSIG) throw new RuntimeException ("entry not found in CEN or premature end...");
+
+ int csize = u32(bytes, pos+0x14); // +0x14 1 dword csize
+ int uncompsize = u32(bytes, pos+0x18); // +0x18 1 dword uncomp size
+ int filenameLength = u16(bytes, pos+0x1c); // +0x1c 1 word length of filename
+ int extraLength = u16(bytes, pos+0x1e); // +0x1e 1 world length of extra field
+ int commentLength = u16(bytes, pos+0x20); // +0x20 1 world length of file comment
+ filename = new String(bytes, pos+0x2e, filenameLength); // +0x2e chars of filename
+ int offset = u32(bytes, pos+0x2a); // +0x2a chars of filename
+
+ System.out.println("filename = " + filename + "\ncsize = " + csize +
+ " uncomp.size = " + uncompsize +" file offset = " + offset);
+ nextPos = pos + 0x2e + filenameLength + extraLength + commentLength;
+
+ } while (!filename.equals(entryName));
+
+ System.out.println("entry found at pos = " + pos);
+ return pos;
+ }
+
+ static int u8(byte[] data, int offset) {
+ return data[offset]&0xff;
+ }
+
+ static int u16(byte[] data, int offset) {
+ return u8(data,offset) + (u8(data,offset+1)<<8);
+ }
+
+ static int u32(byte[] data, int offset) {
+ return u16(data,offset) + (u16(data,offset+2)<<16);
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/Test6842838.sh Mon Sep 14 20:55:08 2009 +0100
@@ -0,0 +1,75 @@
+#!/bin/sh -x
+
+#
+# @test @(#)Test6842838.sh
+# @bug 6842838
+# @summary Test 6842838 64-bit launcher failure due to corrupt jar
+# @run shell Test6842838.sh
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ echo "TESTJAVA not set, selecting " ${TESTJAVA}
+ echo "If this is incorrect, try setting the variable manually."
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ NULL=/dev/null
+ PS=":"
+ FS="/"
+ JAVA_EXE=${TESTJAVA}${FS}bin${FS}sparcv9${FS}java
+ ;;
+ * )
+ echo "Only testing on sparcv9 (use libumem to reliably catch buffer overrun)"
+ exit 0;
+ ;;
+esac
+
+BADFILE=newbadjar.jar
+
+${JAVA_EXE} -version
+rm -f ${BADFILE}
+${TESTJAVA}/bin/javac CreateBadJar.java
+${JAVA_EXE} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF"
+LD_PRELOAD=/lib/64/libumem.so ${JAVA_EXE} -jar ${BADFILE} > test.out 2>&1
+
+grep "Invalid or corrupt jarfile" test.out
+exit $?