# HG changeset patch # User kevinw # Date 1252958108 -3600 # Node ID 2c2395fb6d85d18554c0782c13a44202a1b9b5a7 # Parent 821abab95d386ea891a3b4b79ae8e15d74c58bbf 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 diff -r 821abab95d38 -r 2c2395fb6d85 jdk/src/share/bin/parse_manifest.c --- 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); diff -r 821abab95d38 -r 2c2395fb6d85 jdk/test/tools/launcher/6842838/CreateBadJar.java --- /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); + } + +} + diff -r 821abab95d38 -r 2c2395fb6d85 jdk/test/tools/launcher/6842838/Test6842838.sh --- /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 $?