JDK-2166643 : extcheck.exe -verbose throws ArrayIndexOutOfBoundsException exception
  • Type: Backport
  • Backport of: JDK-6356642
  • Component: tools
  • Sub-Component: jar
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2008-09-04
  • Updated: 2010-12-08
  • Resolved: 2008-10-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 Other
7Fixed OpenJDK6Fixed
Comments
SUGGESTED FIX --- old/src/share/classes/com/sun/tools/extcheck/ExtCheck.java Thu Oct 23 21:50:41 2008 +++ new/src/share/classes/com/sun/tools/extcheck/ExtCheck.java Thu Oct 23 21:50:41 2008 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 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 @@ -256,13 +256,13 @@ private boolean isNotOlderThan(String already,String target) throws NumberFormatException { - if (already == null || already.length() < 1) { + if (already == null || already.length() < 1) { throw new NumberFormatException("Empty version string"); } - // Until it matches scan and compare numbers - StringTokenizer dtok = new StringTokenizer(target, ".", true); - StringTokenizer stok = new StringTokenizer(already, ".", true); + // Until it matches scan and compare numbers + StringTokenizer dtok = new StringTokenizer(target, ".", true); + StringTokenizer stok = new StringTokenizer(already, ".", true); while (dtok.hasMoreTokens() || stok.hasMoreTokens()) { int dver; int sver; @@ -276,19 +276,19 @@ } else sver = 0; - if (sver < dver) - return false; // Known to be incompatible - if (sver > dver) - return true; // Known to be compatible + if (sver < dver) + return false; // Known to be incompatible + if (sver > dver) + return true; // Known to be compatible - // Check for and absorb separators - if (dtok.hasMoreTokens()) - dtok.nextToken(); - if (stok.hasMoreTokens()) - stok.nextToken(); - // Compare next component - } - // All components numerically equal + // Check for and absorb separators + if (dtok.hasMoreTokens()) + dtok.nextToken(); + if (stok.hasMoreTokens()) + stok.nextToken(); + // Compare next component + } + // All components numerically equal return true; } @@ -307,11 +307,10 @@ } /** - * Print out the error message and exit from the program + * Throws a RuntimeException with a message describing the error. */ - static void error(String message){ - System.err.println(message); - System.exit(-1); + static void error(String message) throws RuntimeException { + throw new RuntimeException(message); } @@ -356,19 +355,19 @@ } private JarFile findJarFile(URL url) throws IOException { - // Optimize case where url refers to a local jar file - if ("file".equals(url.getProtocol())) { - String path = url.getFile().replace('/', File.separatorChar); - File file = new File(path); - if (!file.exists()) { - throw new FileNotFoundException(path); - } - return new JarFile(path); - } - URLConnection uc = getBaseURL().openConnection(); - //uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION); - return ((JarURLConnection)uc).getJarFile(); - } + // Optimize case where url refers to a local jar file + if ("file".equals(url.getProtocol())) { + String path = url.getFile().replace('/', File.separatorChar); + File file = new File(path); + if (!file.exists()) { + throw new FileNotFoundException(path); + } + return new JarFile(path); + } + URLConnection uc = getBaseURL().openConnection(); + //uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION); + return ((JarURLConnection)uc).getJarFile(); + } /* @@ -406,6 +405,4 @@ return urls; } } - - } --- old/src/share/classes/com/sun/tools/extcheck/Main.java Thu Oct 23 21:50:43 2008 +++ new/src/share/classes/com/sun/tools/extcheck/Main.java Thu Oct 23 21:50:43 2008 @@ -1,5 +1,5 @@ /* - * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 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 @@ -32,8 +32,11 @@ */ public final class Main { + public static final String INSUFFICIENT = "Insufficient number of arguments"; + public static final String MISSING = "Missing <jar file> argument"; + public static final String DOES_NOT_EXIST = "Jarfile does not exist: "; + public static final String EXTRA = "Extra command line argument: "; - /** * Terminates with one of the following codes * 1 A newer (or same version) jar file is already installed @@ -40,26 +43,36 @@ * 0 No newer jar file was found * -1 An internal error occurred */ - public static void main(String args[]){ - - if (args.length < 1){ - System.err.println("Usage: extcheck [-verbose] <jar file>"); + public static void main(String args[]) { + try { + realMain(args); + } catch (Exception ex) { + System.err.println(ex.getMessage()); System.exit(-1); } + } + + public static void realMain(String[] args) throws Exception { + if (args.length < 1) { + usage(INSUFFICIENT); + } int argIndex = 0; boolean verboseFlag = false; - if (args[argIndex].equals("-verbose")){ + if (args[argIndex].equals("-verbose")) { verboseFlag = true; argIndex++; + if (argIndex >= args.length) { + usage(MISSING); + } } String jarName = args[argIndex]; argIndex++; File jarFile = new File(jarName); if (!jarFile.exists()){ - ExtCheck.error("Jarfile " + jarName + " does not exist"); + usage(DOES_NOT_EXIST + jarName); } if (argIndex < args.length) { - ExtCheck.error("Extra command line argument :"+args[argIndex]); + usage(EXTRA + args[argIndex]); } ExtCheck jt = ExtCheck.create(jarFile,verboseFlag); boolean result = jt.checkInstalledAgainstTarget(); @@ -68,7 +81,9 @@ } else { System.exit(1); } - } + private static void usage(String msg) throws Exception { + throw new Exception(msg + "\nUsage: extcheck [-verbose] <jar file>"); + } } --- /dev/null Thu Oct 23 21:50:45 2008 +++ new/test/com/sun/tools/extcheck/TestExtcheckArgs.java Thu Oct 23 21:50:45 2008 @@ -0,0 +1,92 @@ +/* + * Copyright 2008 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. + */ + +/** + * @test + * @bug 6356642 + * @summary Verify that extcheck exits appropriately when invalid args are given. + * @run shell TestExtcheckArgs.sh + * @author Dave Bristor + */ + +import java.io.File; +import com.sun.tools.extcheck.Main; + +/* + * Test extcheck by using Runtime.exec instead of invoking + * com.sun.tools.extcheck.Main.main, since the latter does its own + * System.exit under the conditions checked here. + */ +public class TestExtcheckArgs { + public static void realMain(String[] args) throws Throwable { + String testJar = System.getenv("TESTJAVA") + File.separator + + "lib" + File.separator + "jconsole.jar"; + + verify(new String[] { + }, Main.INSUFFICIENT); + verify(new String[] { + "-verbose" + }, Main.MISSING); + verify(new String[] { + "-verbose", + "foo" + }, Main.DOES_NOT_EXIST); + verify(new String[] { + testJar, + "bar" + }, Main.EXTRA); + verify(new String[] { + "-verbose", + testJar, + "bar" + }, Main.EXTRA); + } + + static void verify(String[] args, String expected) throws Throwable { + try { + Main.realMain(args); + fail(); + } catch (Exception ex) { + if (ex.getMessage().startsWith(expected)) { + pass(); + } else { + fail("Unexpected message: " + ex.getMessage()); + } + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static boolean pass() {passed++; return true;} + static boolean fail() {failed++; Thread.dumpStack(); return false;} + static boolean fail(String msg) {System.out.println(msg); return fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} + static boolean equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) return pass(); + else return fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} --- /dev/null Thu Oct 23 21:50:46 2008 +++ new/test/com/sun/tools/extcheck/TestExtcheckArgs.sh Thu Oct 23 21:50:46 2008 @@ -0,0 +1,47 @@ +#! /bin/sh + +# +# Copyright 2008 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 [ "x$TESTJAVA" = x ]; then + TESTJAVA=$1; shift + TESTCLASSES=. + TESTSRC=. +fi +export TESTJAVA + +case "`uname`" in Windows*|CYGWIN* ) PS=';';; *) PS=':';; esac + +${TESTJAVA}/bin/javac -d ${TESTCLASSES} -classpath ${TESTJAVA}/lib/tools.jar${PS}${TESTCLASSES} ${TESTSRC}/TestExtcheckArgs.java +rc=$? +if [ $rc != 0 ]; then + echo Compilation failure with exit status $rc + exit $rc +fi + +${TESTJAVA}/bin/java -classpath ${TESTJAVA}/lib/tools.jar${PS}${TESTCLASSES} TestExtcheckArgs +rc=$? +if [ $rc != 0 ]; then + echo Execution failure with exit status $rc + exit $rc +fi
24-10-2008

EVALUATION Yes, the command shouldn't crash.
23-10-2008