1/* 2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 6567415 27 * @summary Test to ensure javac does not go into an infinite loop, while 28 * reading a classfile of a specific length. 29 * @modules jdk.compiler/com.sun.tools.javac.jvm 30 * @compile -XDignore.symbol.file T6567415.java 31 * @run main T6567415 32 * @author ksrini 33 */ 34 35import java.io.File; 36import java.io.FileInputStream; 37import java.io.FileOutputStream; 38import java.io.IOException; 39import java.io.PrintStream; 40import java.io.RandomAccessFile; 41import java.nio.ByteBuffer; 42import java.nio.MappedByteBuffer; 43import java.nio.channels.FileChannel; 44 45/* 46 * this test compiles Bar.java into a classfile and enlarges the file to the 47 * magic file length, then use this mutated file on the classpath to compile 48 * Foo.java which references Bar.java and Ka-boom. QED. 49 */ 50public class T6567415 { 51 final static String TEST_FILE_NAME = "Bar"; 52 final static String TEST_JAVA = TEST_FILE_NAME + ".java"; 53 final static String TEST_CLASS = TEST_FILE_NAME + ".class"; 54 55 final static String TEST2_FILE_NAME = "Foo"; 56 final static String TEST2_JAVA = TEST2_FILE_NAME + ".java"; 57 58 /* 59 * the following is the initial buffer length set in ClassReader.java 60 * thus this value needs to change if ClassReader buf length changes. 61 */ 62 63 final static int BAD_FILE_LENGTH = 64 com.sun.tools.javac.jvm.ClassReader.INITIAL_BUFFER_SIZE; 65 66 static void createClassFile() throws IOException { 67 FileOutputStream fos = null; 68 try { 69 fos = new FileOutputStream(TEST_JAVA); 70 PrintStream ps = new PrintStream(fos); 71 ps.println("public class " + TEST_FILE_NAME + " {}"); 72 } finally { 73 fos.close(); 74 } 75 String cmds[] = {TEST_JAVA}; 76 com.sun.tools.javac.Main.compile(cmds); 77 } 78 79 static void enlargeClassFile() throws IOException { 80 File f = new File(TEST_CLASS); 81 if (!f.exists()) { 82 System.out.println("file not found: " + TEST_CLASS); 83 System.exit(1); 84 } 85 File tfile = new File(f.getAbsolutePath() + ".tmp"); 86 f.renameTo(tfile); 87 88 RandomAccessFile raf = null; 89 FileChannel wfc = null; 90 91 FileInputStream fis = null; 92 FileChannel rfc = null; 93 94 try { 95 raf = new RandomAccessFile(f, "rw"); 96 wfc = raf.getChannel(); 97 98 fis = new FileInputStream(tfile); 99 rfc = fis.getChannel(); 100 101 ByteBuffer bb = MappedByteBuffer.allocate(BAD_FILE_LENGTH); 102 rfc.read(bb); 103 bb.rewind(); 104 wfc.write(bb); 105 wfc.truncate(BAD_FILE_LENGTH); 106 } finally { 107 wfc.close(); 108 raf.close(); 109 rfc.close(); 110 fis.close(); 111 } 112 System.out.println("file length = " + f.length()); 113 } 114 115 static void createJavaFile() throws IOException { 116 FileOutputStream fos = null; 117 try { 118 fos = new FileOutputStream(TEST2_JAVA); 119 PrintStream ps = new PrintStream(fos); 120 ps.println("public class " + TEST2_FILE_NAME + 121 " {" + TEST_FILE_NAME + " b = new " + 122 TEST_FILE_NAME + " ();}"); 123 } finally { 124 fos.close(); 125 } 126 } 127 128 public static void main(String... args) throws Exception { 129 createClassFile(); 130 enlargeClassFile(); 131 createJavaFile(); 132 Thread t = new Thread () { 133 @Override 134 public void run() { 135 String cmds[] = {"-verbose", "-cp", ".", TEST2_JAVA}; 136 int ret = com.sun.tools.javac.Main.compile(cmds); 137 System.out.println("test compilation returns: " + ret); 138 } 139 }; 140 t.start(); 141 t.join(1000*60); 142 System.out.println(t.getState()); 143 if (t.isAlive()) { 144 throw new RuntimeException("Error: compilation is looping"); 145 } 146 } 147} 148