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 /testlibrary /test/lib 31 * @build java.base/java.lang.Helper 32 * @build compiler.intrinsics.string.TestStringIntrinsicRangeChecks 33 * @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:-TieredCompilation compiler.intrinsics.string.TestStringIntrinsicRangeChecks 34 */ 35 package compiler.intrinsics.string; 36 37 import java.lang.Helper; 38 import java.lang.reflect.InvocationTargetException; 39 import java.lang.reflect.Method; 40 41 public class TestStringIntrinsicRangeChecks { 42 // Prepare test arrays 43 private static int SIZE = 16; 44 private static byte[] byteArray = new byte[SIZE]; 45 private static char[] charArray = new char[SIZE]; 46 47 public static void check(Method m, boolean shouldThrow, Object... args) throws Exception { 48 // Prepare error message 49 String message = m.getName() + "("; 50 for (int i = 0; i < args.length; ++i) { 51 message += args[i]; 52 message += (i+1 < args.length) ? ", " : ")"; 53 } 54 55 try { 56 m.invoke(null, args); 57 } catch (InvocationTargetException e) { 58 // Get actual exception 59 Throwable t = e.getTargetException(); 60 if (!shouldThrow) { 61 throw new RuntimeException("Unexpected exception thrown for " + message, e); 62 } 63 if (t instanceof StringIndexOutOfBoundsException || 64 t instanceof ArrayIndexOutOfBoundsException) { 65 // Expected exception. Make sure that the exception was not thrown in UTF16.putChar/getChar 66 // because the corresponding intrinsics are unchecked and the Java code should do all the checks. 67 StackTraceElement[] stack = t.getStackTrace(); 68 if (stack.length != 0) { 69 String methodName = stack[0].getMethodName(); 70 if (methodName.equals("putChar") || methodName.equals("getChar")) { 71 throw new RuntimeException("Exception thrown in " + methodName + " for " + message, t); 72 } 73 } 74 } 75 return; 76 } 77 if (shouldThrow) { 78 throw new RuntimeException("No exception thrown for " + message); 79 } 80 } 81 82 public static void main(String[] args) throws Exception { 83 // Get intrinsified String API methods 84 Method compressByte = Helper.class.getMethod("compressByte", byte[].class, int.class, int.class, int.class, int.class); 85 Method compressChar = Helper.class.getMethod("compressChar", char[].class, int.class, int.class, int.class, int.class); 86 Method inflateByte = Helper.class.getMethod("inflateByte", byte[].class, int.class, int.class, int.class, int.class); 87 Method inflateChar = Helper.class.getMethod("inflateChar", byte[].class, int.class, int.class, int.class, int.class); 88 Method toBytes = Helper.class.getMethod("toBytes", char[].class, int.class, int.class); 89 Method getChars = Helper.class.getMethod("getChars", byte[].class, int.class, int.class, int.class, int.class); 90 91 // Check different combinations of arguments (source/destination offset and length) 92 for (int srcOff = 0; srcOff < SIZE; ++srcOff) { 93 for (int dstOff = 0; dstOff < SIZE; ++dstOff) { 94 for (int len = 0; len < SIZE; ++len) { 95 // Check for potential overlows in source or destination array 96 boolean srcOverflow = (srcOff + len) > SIZE; 97 boolean srcOverflowB = (2*srcOff + 2*len) > SIZE; 98 boolean dstOverflow = (dstOff + len) > SIZE; 99 boolean dstOverflowB = (2*dstOff + 2*len) > SIZE; 100 boolean getCharsOver = (srcOff < len) && ((2*(len-1) >= SIZE) || ((dstOff + len - srcOff) > SIZE)); 101 // Check if an exception is thrown and bail out if result is inconsistent with above 102 // assumptions (for example, an exception was not thrown although an overflow happened). 103 check(compressByte, srcOverflowB || dstOverflow, byteArray, srcOff, SIZE, dstOff, len); 104 check(compressChar, srcOverflow || dstOverflow, charArray, srcOff, SIZE, dstOff, len); 105 check(inflateByte, srcOverflow || dstOverflowB, byteArray, srcOff, SIZE, dstOff, len); 106 check(inflateChar, srcOverflow || dstOverflow, byteArray, srcOff, SIZE, dstOff, len); 107 check(toBytes, srcOverflow, charArray, srcOff, len); 108 check(getChars, getCharsOver, byteArray, srcOff, len, SIZE, dstOff); 109 } 110 } 111 } 112 } 113 }