1 /* 2 * Copyright (c) 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * @test 28 * @bug 8155608 29 * @summary Verifies that string intrinsics throw array out of bounds exceptions. 30 * @library /compiler/patches /test/lib 31 * @build java.base/java.lang.Helper 32 * @run main/othervm -Xbatch -XX:CompileThreshold=100 compiler.intrinsics.string.TestStringIntrinsicRangeChecks 33 */ 34 package compiler.intrinsics.string; 35 36 import java.lang.Helper; 37 import java.lang.reflect.InvocationTargetException; 38 import java.lang.reflect.Method; 39 40 public class TestStringIntrinsicRangeChecks { 41 // Prepare test arrays 42 private static int SIZE = 16; 43 private static byte[] byteArray = new byte[SIZE]; 44 private static char[] charArray = new char[SIZE]; 45 46 public static void check(Method m, boolean shouldThrow, Object... args) throws Exception { 47 // Prepare error message 48 String message = m.getName() + "("; 49 for (int i = 0; i < args.length; ++i) { 50 message += args[i]; 51 message += (i+1 < args.length) ? ", " : ")"; 52 } 53 54 try { 55 m.invoke(null, args); 56 } catch (InvocationTargetException e) { 57 // Get actual exception 58 Throwable t = e.getTargetException(); 59 if (!shouldThrow) { 60 throw new RuntimeException("Unexpected exception thrown for " + message, e); 61 } 62 if (t instanceof StringIndexOutOfBoundsException || 63 t instanceof ArrayIndexOutOfBoundsException) { 64 // Expected exception. Make sure that the exception was not thrown in UTF16.putChar/getChar 65 // because the corresponding intrinsics are unchecked and the Java code should do all the checks. 66 StackTraceElement[] stack = t.getStackTrace(); 67 if (stack.length != 0) { 68 String methodName = stack[0].getMethodName(); 69 if (methodName.equals("putChar") || methodName.equals("getChar")) { 70 throw new RuntimeException("Exception thrown in " + methodName + " for " + message, t); 71 } 72 } 73 } 74 return; 75 } 76 if (shouldThrow) { 77 throw new RuntimeException("No exception thrown for " + message); 78 } 79 } 80 81 public static void main(String[] args) throws Exception { 82 // Get intrinsified String API methods 83 Method compressByte = Helper.class.getMethod("compressByte", byte[].class, int.class, int.class, int.class, int.class); 84 Method compressChar = Helper.class.getMethod("compressChar", char[].class, int.class, int.class, int.class, int.class); 85 Method inflateByte = Helper.class.getMethod("inflateByte", byte[].class, int.class, int.class, int.class, int.class); 86 Method inflateChar = Helper.class.getMethod("inflateChar", byte[].class, int.class, int.class, int.class, int.class); 87 Method toBytes = Helper.class.getMethod("toBytes", char[].class, int.class, int.class); 88 Method getChars = Helper.class.getMethod("getChars", byte[].class, int.class, int.class, int.class, int.class); 89 90 // Check different combinations of arguments (source/destination offset and length) 91 for (int srcOff = 0; srcOff < SIZE; ++srcOff) { 92 for (int dstOff = 0; dstOff < SIZE; ++dstOff) { 93 for (int len = 0; len < SIZE; ++len) { 94 // Check for potential overlows in source or destination array 95 boolean srcOverflow = (srcOff + len) > SIZE; 96 boolean srcOverflowB = (2*srcOff + 2*len) > SIZE; 97 boolean dstOverflow = (dstOff + len) > SIZE; 98 boolean dstOverflowB = (2*dstOff + 2*len) > SIZE; 99 boolean getCharsOver = (srcOff < len) && ((2*(len-1) >= SIZE) || ((dstOff + len - srcOff) > SIZE)); 100 // Check if an exception is thrown and bail out if result is inconsistent with above 101 // assumptions (for example, an exception was not thrown although an overflow happened). 102 check(compressByte, srcOverflowB || dstOverflow, byteArray, srcOff, SIZE, dstOff, len); 103 check(compressChar, srcOverflow || dstOverflow, charArray, srcOff, SIZE, dstOff, len); 104 check(inflateByte, srcOverflow || dstOverflowB, byteArray, srcOff, SIZE, dstOff, len); 105 check(inflateChar, srcOverflow || dstOverflow, byteArray, srcOff, SIZE, dstOff, len); 106 check(toBytes, srcOverflow, charArray, srcOff, len); 107 check(getChars, getCharsOver, byteArray, srcOff, len, SIZE, dstOff); 108 } 109 } 110 } 111 } 112 }