ksrini@804: /* ksrini@804: * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. ksrini@804: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ksrini@804: * ksrini@804: * This code is free software; you can redistribute it and/or modify it ksrini@804: * under the terms of the GNU General Public License version 2 only, as ksrini@804: * published by the Free Software Foundation. ksrini@804: * ksrini@804: * This code is distributed in the hope that it will be useful, but WITHOUT ksrini@804: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ksrini@804: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ksrini@804: * version 2 for more details (a copy is included in the LICENSE file that ksrini@804: * accompanied this code). ksrini@804: * ksrini@804: * You should have received a copy of the GNU General Public License version ksrini@804: * 2 along with this work; if not, write to the Free Software Foundation, ksrini@804: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ksrini@804: * ksrini@804: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ksrini@804: * or visit www.oracle.com if you need additional information or have any ksrini@804: * questions. ksrini@804: */ ksrini@804: ksrini@804: /* ksrini@804: * @test ksrini@804: * @bug 6567415 ksrini@804: * @summary Test to ensure javac does not go into an infinite loop, while ksrini@804: * reading a classfile of a specific length. ksrini@804: * @compile -XDignore.symbol.file T6567415.java ksrini@804: * @run main T6567415 ksrini@804: * @author ksrini ksrini@804: */ ksrini@804: ksrini@804: import java.io.File; ksrini@804: import java.io.FileInputStream; ksrini@804: import java.io.FileOutputStream; ksrini@804: import java.io.IOException; ksrini@804: import java.io.PrintStream; ksrini@804: import java.io.RandomAccessFile; ksrini@804: import java.nio.ByteBuffer; ksrini@804: import java.nio.MappedByteBuffer; ksrini@804: import java.nio.channels.FileChannel; ksrini@804: ksrini@804: /* ksrini@804: * this test compiles Bar.java into a classfile and enlarges the file to the ksrini@804: * magic file length, then use this mutated file on the classpath to compile ksrini@804: * Foo.java which references Bar.java and Ka-boom. QED. ksrini@804: */ ksrini@804: public class T6567415 { ksrini@804: final static String TEST_FILE_NAME = "Bar"; ksrini@804: final static String TEST_JAVA = TEST_FILE_NAME + ".java"; ksrini@804: final static String TEST_CLASS = TEST_FILE_NAME + ".class"; ksrini@804: ksrini@804: final static String TEST2_FILE_NAME = "Foo"; ksrini@804: final static String TEST2_JAVA = TEST2_FILE_NAME + ".java"; ksrini@804: ksrini@804: /* ksrini@804: * the following is the initial buffer length set in ClassReader.java ksrini@804: * thus this value needs to change if ClassReader buf length changes. ksrini@804: */ ksrini@804: ksrini@804: final static int BAD_FILE_LENGTH = ksrini@804: com.sun.tools.javac.jvm.ClassReader.INITIAL_BUFFER_SIZE; ksrini@804: ksrini@804: static void createClassFile() throws IOException { ksrini@804: FileOutputStream fos = null; ksrini@804: try { ksrini@804: fos = new FileOutputStream(TEST_JAVA); ksrini@804: PrintStream ps = new PrintStream(fos); ksrini@804: ps.println("public class " + TEST_FILE_NAME + " {}"); ksrini@804: } finally { ksrini@804: fos.close(); ksrini@804: } ksrini@804: String cmds[] = {TEST_JAVA}; ksrini@804: com.sun.tools.javac.Main.compile(cmds); ksrini@804: } ksrini@804: ksrini@804: static void enlargeClassFile() throws IOException { ksrini@804: File f = new File(TEST_CLASS); ksrini@804: if (!f.exists()) { ksrini@804: System.out.println("file not found: " + TEST_CLASS); ksrini@804: System.exit(1); ksrini@804: } ksrini@804: File tfile = new File(f.getAbsolutePath() + ".tmp"); ksrini@804: f.renameTo(tfile); ksrini@804: ksrini@804: RandomAccessFile raf = null; ksrini@804: FileChannel wfc = null; ksrini@804: ksrini@804: FileInputStream fis = null; ksrini@804: FileChannel rfc = null; ksrini@804: ksrini@804: try { ksrini@804: raf = new RandomAccessFile(f, "rw"); ksrini@804: wfc = raf.getChannel(); ksrini@804: ksrini@804: fis = new FileInputStream(tfile); ksrini@804: rfc = fis.getChannel(); ksrini@804: ksrini@804: ByteBuffer bb = MappedByteBuffer.allocate(BAD_FILE_LENGTH); ksrini@804: rfc.read(bb); ksrini@804: bb.rewind(); ksrini@804: wfc.write(bb); ksrini@804: wfc.truncate(BAD_FILE_LENGTH); ksrini@804: } finally { ksrini@804: wfc.close(); ksrini@804: raf.close(); ksrini@804: rfc.close(); ksrini@804: fis.close(); ksrini@804: } ksrini@804: System.out.println("file length = " + f.length()); ksrini@804: } ksrini@804: ksrini@804: static void createJavaFile() throws IOException { ksrini@804: FileOutputStream fos = null; ksrini@804: try { ksrini@804: fos = new FileOutputStream(TEST2_JAVA); ksrini@804: PrintStream ps = new PrintStream(fos); ksrini@804: ps.println("public class " + TEST2_FILE_NAME + ksrini@804: " {" + TEST_FILE_NAME + " b = new " + ksrini@804: TEST_FILE_NAME + " ();}"); ksrini@804: } finally { ksrini@804: fos.close(); ksrini@804: } ksrini@804: } ksrini@804: ksrini@804: public static void main(String... args) throws Exception { ksrini@804: createClassFile(); ksrini@804: enlargeClassFile(); ksrini@804: createJavaFile(); ksrini@804: Thread t = new Thread () { ksrini@804: @Override ksrini@804: public void run() { ksrini@804: String cmds[] = {"-verbose", "-cp", ".", TEST2_JAVA}; ksrini@804: int ret = com.sun.tools.javac.Main.compile(cmds); ksrini@804: System.out.println("test compilation returns: " + ret); ksrini@804: } ksrini@804: }; ksrini@804: t.start(); ksrini@804: t.join(1000*10); ksrini@804: System.out.println(t.getState()); ksrini@804: if (t.isAlive()) { ksrini@804: throw new RuntimeException("Error: compilation is looping"); ksrini@804: } ksrini@804: } ksrini@804: }