--- /dev/null 2017-11-08 15:32:50.000000000 -0800 +++ new/test/jdk/java/lang/invoke/InvokeMethodHandleWithBadArgument.java 2017-11-08 15:32:49.000000000 -0800 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8157246 + * @run testng/othervm test.java.lang.invoke.InvokeMethodHandleWithBadArgument + */ + +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +/** + * Tests invocation of MethodHandle with invalid leading argument such as + * MethodHandle, VarHandle, and array object + */ +public class InvokeMethodHandleWithBadArgument { + // ---- null array reference ---- + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testAsSpreaderPosInvokeWithNull() throws Throwable { + MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3); + spreader.invoke("A", null, "B"); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testAsSpreaderInvokeWithNull() throws Throwable { + MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2); + assert ((boolean) spreader.invokeExact(new String[]{"me", "me"})); + boolean eq = (boolean) spreader.invokeExact((String[]) null); + } + + // ---- incorrect array element count ---- + @Test(expectedExceptions = {IllegalArgumentException.class}) + public static void testAsSpreaderPosInvokeWithBadElementCount() throws Throwable { + MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3); + spreader.invoke("A", new int[]{1, 2}, "B"); + } + + @Test(expectedExceptions = {IllegalArgumentException.class}) + public static void testAsSpreaderInvokeWithBadElementCount() throws Throwable { + MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2); + assert (!(boolean) spreader.invokeExact(new String[]{"me", "thee"})); + boolean eq = (boolean) spreader.invokeExact(new String[0]); + } + + @Test(expectedExceptions = {IllegalArgumentException.class}) + public static void testAsSpreaderInvokeWithBadElementCount() throws Throwable { + MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2); + assert (!(boolean) spreader.invokeExact(new String[]{"me", "thee"})); + boolean eq = (boolean) spreader.invokeExact("me"); + } + + // ---- spread no argument ---- + @Test + public static void testAsSpreaderPosInvokeWithZeroLength() throws Throwable { + MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 0); + assert("A123B".equals(spreader.invoke("A", (int[])null, 1, 2, 3, "B"))); + } + + @Test + public static void testAsSpreaderInvokeWithZeroLength() throws Throwable { + MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 0); + assert ((boolean) spreader.invokeExact("me", "me", new String[0])); + boolean eq = (boolean) spreader.invokeExact("me", (Object)"me", (String[]) null); + } + + // ---- invokers with null method/var handle argument ---- + @Test(expectedExceptions = {NullPointerException.class}) + public static void testInvokerWithNull() throws Throwable { + MethodType type = methodType(int.class, int.class, int.class); + MethodHandle invoker = MethodHandles.invoker(type); + assert((int) invoker.invoke(MH_add, 1, 2) == 3); + int sum = (int)invoker.invoke((MethodHandle)null, 1, 2); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testExactInvokerWithNull() throws Throwable { + MethodType type = methodType(int.class, int.class, int.class); + MethodHandle invoker = MethodHandles.exactInvoker(type); + assert((int) invoker.invoke(MH_add, 1, 2) == 3); + int sum = (int)invoker.invokeExact((MethodHandle)null, 1, 2); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testSpreadInvokerWithNull() throws Throwable { + MethodType type = methodType(boolean.class, String.class, String.class); + MethodHandle invoker = MethodHandles.spreadInvoker(type, 0); + assert ((boolean) invoker.invoke(MH_spread, new String[]{"me", "me"})); + boolean eq = (boolean) invoker.invoke((MethodHandle)null, new String[]{"me", "me"}); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testVarHandleInvokerWithNull() throws Throwable { + VarHandle.AccessMode am = VarHandle.AccessMode.GET; + MethodHandle invoker = MethodHandles.varHandleInvoker(am, VH_array.accessModeType(am)); + assert ((int) invoker.invoke(VH_array, array, 3) == 3); + int value = (int)invoker.invoke((VarHandle)null, array, 3); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public static void testVarHandleExactInvokerWithNull() throws Throwable { + VarHandle.AccessMode am = VarHandle.AccessMode.GET; + MethodHandle invoker = MethodHandles.varHandleExactInvoker(am, VH_array.accessModeType(am)); + assert ((int) invoker.invoke(VH_array, array, 3) == 3); + int value = (int)invoker.invokeExact((VarHandle)null, array, 3); + } + + static final Lookup LOOKUP = MethodHandles.lookup(); + static final MethodHandle MH_add; + static final MethodHandle MH_spread; + static final MethodHandle MH_String_equals; + static final VarHandle VH_array; + + static final int[] array = new int[] { 0, 1, 2, 3, 4, 5}; + static { + try { + Class arrayClass = Class.forName("[I"); + VH_array = MethodHandles.arrayElementVarHandle(arrayClass); + MH_add = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "add", + methodType(int.class, int.class, int.class)); + MH_spread = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "spread", + methodType(String.class, String.class, int.class, int.class, int.class, String.class)); + MH_String_equals = LOOKUP.findVirtual(String.class, "equals", methodType(boolean.class, Object.class)); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + static String spread(String s1, int i1, int i2, int i3, String s2) { + return s1 + i1 + i2 + i3 + s2; + } + + static int add(int x, int y) { + return x+y; + } +}