hotspot/test/compiler/intrinsics/string/TestStringIntrinsicRangeChecks.java
changeset 38683 e8a871cf6d09
child 40045 4273f3ba95f7
equal deleted inserted replaced
38676:48614091c64b 38683:e8a871cf6d09
       
     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 compiler.intrinsics.string.TestStringIntrinsicRangeChecks
       
    34  */
       
    35 package compiler.intrinsics.string;
       
    36 
       
    37 import java.lang.Helper;
       
    38 import java.lang.reflect.*;
       
    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 }