mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8363917: SwitchBootstraps.enumSwitch() args not checked as documented
Reviewed-by: liach
This commit is contained in:
parent
2ac24bf1ba
commit
862119565d
@ -165,22 +165,22 @@ public final class SwitchBootstraps {
|
||||
* @param lookup Represents a lookup context with the accessibility
|
||||
* privileges of the caller. When used with {@code invokedynamic},
|
||||
* this is stacked automatically by the VM.
|
||||
* @param invocationName unused
|
||||
* @param invocationName unused, {@code null} is permitted
|
||||
* @param invocationType The invocation type of the {@code CallSite} with two parameters,
|
||||
* a reference type, an {@code int}, and {@code int} as a return type.
|
||||
* @param labels case labels - {@code String} and {@code Integer} constants
|
||||
* and {@code Class} and {@code EnumDesc} instances, in any combination
|
||||
* @return a {@code CallSite} returning the first matching element as described above
|
||||
*
|
||||
* @throws NullPointerException if any argument is {@code null}
|
||||
* @throws NullPointerException if any argument is {@code null}, unless noted otherwise
|
||||
* @throws IllegalArgumentException if any element in the labels array is null
|
||||
* @throws IllegalArgumentException if the invocation type is not a method type of first parameter of a reference type,
|
||||
* second parameter of type {@code int} and with {@code int} as its return type,
|
||||
* second parameter of type {@code int} and with {@code int} as its return type
|
||||
* @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code String},
|
||||
* {@code Integer}, {@code Long}, {@code Float}, {@code Double}, {@code Boolean},
|
||||
* {@code Class} or {@code EnumDesc}.
|
||||
* {@code Class} or {@code EnumDesc}
|
||||
* @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code Boolean}
|
||||
* when {@code target} is a {@code Boolean.class}.
|
||||
* when {@code target} is a {@code Boolean.class}
|
||||
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
|
||||
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
|
||||
*/
|
||||
@ -255,29 +255,36 @@ public final class SwitchBootstraps {
|
||||
* enum constant's {@link Enum#name()}.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If no element in the {@code labels} array matches the target, then
|
||||
* the method of the call site return the length of the {@code labels} array.
|
||||
* If for a given {@code target} there is no element in the {@code labels}
|
||||
* fulfilling one of the above conditions, then the method of the call
|
||||
* site returns the length of the {@code labels} array.
|
||||
* <p>
|
||||
* The value of the {@code restart} index must be between {@code 0} (inclusive) and
|
||||
* the length of the {@code labels} array (inclusive),
|
||||
* both or an {@link IndexOutOfBoundsException} is thrown.
|
||||
* or an {@link IndexOutOfBoundsException} is thrown.
|
||||
*
|
||||
* @apiNote It is permissible for the {@code labels} array to contain {@code String}
|
||||
* values that do not represent any enum constants at runtime.
|
||||
*
|
||||
* @param lookup Represents a lookup context with the accessibility
|
||||
* privileges of the caller. When used with {@code invokedynamic},
|
||||
* this is stacked automatically by the VM.
|
||||
* @param invocationName unused
|
||||
* @param invocationName unused, {@code null} is permitted
|
||||
* @param invocationType The invocation type of the {@code CallSite} with two parameters,
|
||||
* an enum type, an {@code int}, and {@code int} as a return type.
|
||||
* @param labels case labels - {@code String} constants and {@code Class} instances,
|
||||
* in any combination
|
||||
* @return a {@code CallSite} returning the first matching element as described above
|
||||
*
|
||||
* @throws NullPointerException if any argument is {@code null}
|
||||
* @throws IllegalArgumentException if any element in the labels array is null, if the
|
||||
* invocation type is not a method type whose first parameter type is an enum type,
|
||||
* second parameter of type {@code int} and whose return type is {@code int},
|
||||
* or if {@code labels} contains an element that is not of type {@code String} or
|
||||
* {@code Class} of the target enum type.
|
||||
* @throws NullPointerException if any argument is {@code null}, unless noted otherwise
|
||||
* @throws IllegalArgumentException if any element in the labels array is null
|
||||
* @throws IllegalArgumentException if any element in the labels array is an empty {@code String}
|
||||
* @throws IllegalArgumentException if the invocation type is not a method type
|
||||
* whose first parameter type is an enum type,
|
||||
* second parameter of type {@code int} and
|
||||
* whose return type is {@code int}
|
||||
* @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code String} or
|
||||
* {@code Class} equal to the target enum type
|
||||
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
|
||||
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2025, 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
|
||||
@ -155,23 +155,60 @@ public class SwitchBootstrapsTest {
|
||||
testEnum(E1.B, 0, 0, "B", "C", "A", E1.class);
|
||||
testEnum(E1.B, 1, 3, "B", "C", "A", E1.class);
|
||||
try {
|
||||
testEnum(E1.B, 1, 3, "B", "C", "A", E2.class);
|
||||
testEnum(E1.B, 0, -1, E2.class);
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 1, 3, "B", "C", "A", String.class);
|
||||
testEnum(E1.B, 0, -1, String.class);
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 0, -1, 10);
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 0, -1, new Object());
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 0, -1, new Object[] { null });
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 0, -1, "");
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
try {
|
||||
testEnum(E1.B, 0, -1, (Object[]) null);
|
||||
fail("Didn't get the expected exception.");
|
||||
} catch (NullPointerException ex) {
|
||||
//OK
|
||||
}
|
||||
testEnum(E1.B, 0, 0, "B", "A");
|
||||
testEnum(E1.A, 0, 1, "B", "A");
|
||||
testEnum(E1.A, 0, 0, "A", "A", "B");
|
||||
testEnum(E1.A, 1, 1, "A", "A", "B");
|
||||
testEnum(E1.A, 2, 3, "A", "A", "B");
|
||||
testEnum(E1.A, 0, 0);
|
||||
testEnum(E1.B, 0, 2, "A", "OLD_REMOVED_CONSTANT", "B", E1.class);
|
||||
testEnum(E1.B, 1, 2, "A", "OLD_REMOVED_CONSTANT", "B", E1.class);
|
||||
|
||||
//null invocation name:
|
||||
MethodType switchType = MethodType.methodType(int.class, E1.class, int.class);
|
||||
MethodHandle indy = ((CallSite) BSM_ENUM_SWITCH.invoke(MethodHandles.lookup(), null, switchType)).dynamicInvoker();
|
||||
assertEquals((int) indy.invoke(E1.A, 0), 0);
|
||||
}
|
||||
|
||||
public void testEnumsWithConstants() throws Throwable {
|
||||
@ -197,6 +234,9 @@ public class SwitchBootstrapsTest {
|
||||
testEnum(E.class, E.A, 0, 0, "A", "B", "C");
|
||||
testEnum(E.class, E.B, 0, 1, "A", "B", "C");
|
||||
testEnum(E.class, E.C, 0, 2, "A", "B", "C");
|
||||
testEnum(E.class, E.C, 0, 2, "A", "B");
|
||||
testEnum(E.class, E.C, 1, 2, "A", "B");
|
||||
testEnum(E.class, E.C, 2, 2, "A", "B");
|
||||
}
|
||||
|
||||
public void testWrongSwitchTypes() throws Throwable {
|
||||
@ -279,6 +319,9 @@ public class SwitchBootstrapsTest {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//OK
|
||||
}
|
||||
//null invocationName is OK:
|
||||
BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), null, switchType,
|
||||
new Object[] {Object.class});
|
||||
}
|
||||
|
||||
private static AtomicBoolean enumInitialized = new AtomicBoolean();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user