java-topology/test/jdk/java/lang/invoke/condy/CondyBSMInvocation.java
russell@unturf.com 0a580b313d undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
2026-03-26 17:11:57 -04:00

244 lines
8 KiB
Java

/*
* Copyright (c) 2017, 2026, 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.
*
* 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 8186046 8199875
* @summary Test basic invocation of bootstrap methods
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @run junit CondyBSMInvocation
* @run junit/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMInvocation
*/
import test.java.lang.invoke.lib.InstructionHelper;
import java.lang.constant.ConstantDesc;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.lang.invoke.MethodType.methodType;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CondyBSMInvocation {
static final MethodHandles.Lookup L = MethodHandles.lookup();
@Test
public void testNonexistent() throws Throwable {
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"bsm", methodType(Object.class)
);
assertThrows(NoSuchMethodError.class, mh::invoke);
}
static MethodHandle[] bsms(String bsmName) {
return Stream.of(CondyBSMInvocation.class.getDeclaredMethods()).
filter(m -> m.getName().equals(bsmName)).
map(m -> {
try {
return MethodHandles.lookup().unreflect(m);
} catch (IllegalAccessException e) {
throw new RuntimeException();
}
}).toArray(MethodHandle[]::new);
}
public static Object shape_bsm() {
return "0";
}
public static Object shape_bsm(Object a1) {
return "0";
}
public static Object shape_bsm(Object... args) {
return "0";
}
public static Object shape_bsm(Object a1, Object a2) {
return "0";
}
public static Object shape_bsm(Object a1, Object... args) {
return "0";
}
public static Object shape_bsm(Object a1, Object a2, Object a3) {
return "0";
}
public static Object shape_bsm(MethodHandles.Lookup a1) {
return "0";
}
@Test
public void testWrongShape() throws Throwable {
for (MethodHandle bsm : bsms("shape_bsm")) {
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"shape_bsm", bsm.type()
);
assertThrows(BootstrapMethodError.class, mh::invoke);
}
}
public static Object sig_bsm(MethodHandles.Lookup a1, String[] a2) {
return "0";
}
public static Object sig_bsm(MethodHandles.Lookup a1, String a2, String a3) {
return "0";
}
@Test
public void testWrongSignature() throws Throwable {
for (MethodHandle bsm : bsms("sig_bsm")) {
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"sig_bsm", bsm.type()
);
assertThrows(BootstrapMethodError.class, mh::invoke);
}
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type) {
return "0";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1) {
assertAll(a1);
return "1";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2) {
assertAll(a1, a2);
return "2";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2, Object a3) {
assertAll(a1, a2, a3);
return "3";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2, Object a3, Object a4) {
assertAll(a1, a2, a3, a4);
return "4";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2, Object a3, Object a4, Object a5) {
assertAll(a1, a2, a3, a4, a5);
return "5";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
assertAll(a1, a2, a3, a4, a5, a6);
return "6";
}
public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type,
Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
assertAll(a1, a2, a3, a4, a5, a6, a7);
return "7";
}
public static Object bsm(MethodHandles.Lookup l, Object... args) {
Object[] staticArgs = Arrays.copyOfRange(args, 2, args.length);
assertAll(staticArgs);
return Integer.toString(staticArgs.length);
}
static void assertAll(Object... as) {
for (int i = 0; i < as.length; i++) {
assertEquals(i, as[i]);
}
}
@Test
public void testArity() throws Throwable {
for (int i = 0; i < 8; i++) {
final int n = i;
MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class)
.appendParameterTypes(Collections.nCopies(n, Object.class));
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"bsm", mt,
IntStream.range(0, n).boxed().toArray(ConstantDesc[]::new)
);
Object r = mh.invoke();
assertEquals(Integer.toString(n), r);
}
{
MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, Object[].class);
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"bsm", mt,
IntStream.range(0, 9).boxed().toArray(ConstantDesc[]::new)
);
Object r = mh.invoke();
assertEquals(Integer.toString(9), r);
}
}
@Test
public void testWrongNumberOfStaticArguments() throws Throwable {
for (int i = 1; i < 8; i++) {
final int n = i;
MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class)
.appendParameterTypes(Collections.nCopies(n, Object.class));
MethodHandle mh = InstructionHelper.ldcDynamicConstant(
L, "name", Object.class,
"bsm", mt,
IntStream.range(0, n - 1).boxed().toArray(ConstantDesc[]::new)
);
var e = assertThrows(BootstrapMethodError.class, mh::invoke);
assertInstanceOf(WrongMethodTypeException.class, e.getCause());
}
}
}