/* * Copyright (c) 2010, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 6567415 * @summary Test to ensure javac does not go into an infinite loop, while * reading a classfile of a specific length. * @modules jdk.compiler/com.sun.tools.javac.jvm * @compile -XDignore.symbol.file T6567415.java * @run main T6567415 * @author ksrini */ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; /* * this test compiles Bar.java into a classfile and enlarges the file to the * magic file length, then use this mutated file on the classpath to compile * Foo.java which references Bar.java and Ka-boom. QED. */ public class T6567415 { final static String TEST_FILE_NAME = "Bar"; final static String TEST_JAVA = TEST_FILE_NAME + ".java"; final static String TEST_CLASS = TEST_FILE_NAME + ".class"; final static String TEST2_FILE_NAME = "Foo"; final static String TEST2_JAVA = TEST2_FILE_NAME + ".java"; /* * the following is the initial buffer length set in ClassReader.java * thus this value needs to change if ClassReader buf length changes. */ final static int BAD_FILE_LENGTH = com.sun.tools.javac.jvm.ClassReader.INITIAL_BUFFER_SIZE; static void createClassFile() throws IOException { FileOutputStream fos = null; try { fos = new FileOutputStream(TEST_JAVA); PrintStream ps = new PrintStream(fos); ps.println("public class " + TEST_FILE_NAME + " {}"); } finally { fos.close(); } String cmds[] = {TEST_JAVA}; com.sun.tools.javac.Main.compile(cmds); } static void enlargeClassFile() throws IOException { File f = new File(TEST_CLASS); if (!f.exists()) { System.out.println("file not found: " + TEST_CLASS); System.exit(1); } File tfile = new File(f.getAbsolutePath() + ".tmp"); f.renameTo(tfile); RandomAccessFile raf = null; FileChannel wfc = null; FileInputStream fis = null; FileChannel rfc = null; try { raf = new RandomAccessFile(f, "rw"); wfc = raf.getChannel(); fis = new FileInputStream(tfile); rfc = fis.getChannel(); ByteBuffer bb = MappedByteBuffer.allocate(BAD_FILE_LENGTH); rfc.read(bb); bb.rewind(); wfc.write(bb); wfc.truncate(BAD_FILE_LENGTH); } finally { wfc.close(); raf.close(); rfc.close(); fis.close(); } System.out.println("file length = " + f.length()); } static void createJavaFile() throws IOException { FileOutputStream fos = null; try { fos = new FileOutputStream(TEST2_JAVA); PrintStream ps = new PrintStream(fos); ps.println("public class " + TEST2_FILE_NAME + " {" + TEST_FILE_NAME + " b = new " + TEST_FILE_NAME + " ();}"); } finally { fos.close(); } } public static void main(String... args) throws Exception { createClassFile(); enlargeClassFile(); createJavaFile(); Thread t = new Thread () { @Override public void run() { String cmds[] = {"-verbose", "-cp", ".", TEST2_JAVA}; int ret = com.sun.tools.javac.Main.compile(cmds); System.out.println("test compilation returns: " + ret); } }; t.start(); t.join(1000*60); System.out.println(t.getState()); if (t.isAlive()) { throw new RuntimeException("Error: compilation is looping"); } } }