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