8354323: Safeguard SwitchBootstraps.typeSwitch when used outside the compiler
Reviewed-by: jlahoda, liach
This commit is contained in:
parent
85b24c3c4e
commit
c0665efd4f
@ -546,7 +546,11 @@ public final class SwitchBootstraps {
|
||||
Object caseLabel = caseLabels[idx];
|
||||
cb.labelBinding(caseTargets[idx]);
|
||||
if (caseLabel instanceof Class<?> classLabel) {
|
||||
if (unconditionalExactnessCheck(selectorType, classLabel)) {
|
||||
if (isNotValidPair(selectorType, caseLabel)){
|
||||
cb.goto_(next);
|
||||
continue;
|
||||
}
|
||||
else if (unconditionalExactnessCheck(selectorType, classLabel)) {
|
||||
//nothing - unconditionally use this case
|
||||
} else if (classLabel.isPrimitive()) {
|
||||
if (!selectorType.isPrimitive() && !Wrapper.isWrapperNumericOrBooleanType(selectorType)) {
|
||||
@ -717,6 +721,11 @@ public final class SwitchBootstraps {
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isNotValidPair(Class<?> selectorType, Object caseLabel) {
|
||||
return (selectorType == boolean.class && caseLabel != boolean.class && caseLabel != Boolean.class) ||
|
||||
(selectorType != boolean.class && selectorType.isPrimitive() && (caseLabel == boolean.class || caseLabel == Boolean.class));
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
|
||||
*/
|
||||
@ -769,11 +778,11 @@ public final class SwitchBootstraps {
|
||||
return true;
|
||||
}
|
||||
else if (selectorType.equals(targetType) ||
|
||||
((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
|
||||
(selectorType.equals(short.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) ||
|
||||
(selectorType.equals(char.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) ||
|
||||
(selectorType.equals(int.class) && (targetType.equals(double.class) || targetType.equals(long.class))) ||
|
||||
(selectorType.equals(float.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))))) return true;
|
||||
(targetType.isPrimitive() && selectorType.isPrimitive() &&
|
||||
(selectorWrapper.isStrictSubRangeOf(targetWrapper) &&
|
||||
!((selectorType.equals(byte.class) && targetType.equals(char.class)) ||
|
||||
(selectorType.equals(int.class) && targetType.equals(float.class)) ||
|
||||
(selectorType.equals(long.class) && (targetType.equals(double.class) || targetType.equals(float.class))))))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5085,16 +5085,12 @@ public class Types {
|
||||
* @param targetType Target type
|
||||
*/
|
||||
public boolean isUnconditionallyExactPrimitives(Type selectorType, Type targetType) {
|
||||
if (isSameType(selectorType, targetType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (selectorType.isPrimitive() && targetType.isPrimitive()) &&
|
||||
((selectorType.hasTag(BYTE) && !targetType.hasTag(CHAR)) ||
|
||||
(selectorType.hasTag(SHORT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) ||
|
||||
(selectorType.hasTag(CHAR) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) ||
|
||||
(selectorType.hasTag(INT) && (targetType.hasTag(DOUBLE) || targetType.hasTag(LONG))) ||
|
||||
(selectorType.hasTag(FLOAT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))));
|
||||
return isSameType(selectorType, targetType) ||
|
||||
(selectorType.isPrimitive() && targetType.isPrimitive()) &&
|
||||
((selectorType.getTag().isStrictSubRangeOf(targetType.getTag())) &&
|
||||
!((selectorType.hasTag(BYTE) && targetType.hasTag(CHAR)) ||
|
||||
(selectorType.hasTag(INT) && targetType.hasTag(FLOAT)) ||
|
||||
(selectorType.hasTag(LONG) && (targetType.hasTag(DOUBLE) || targetType.hasTag(FLOAT)))));
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
|
@ -74,6 +74,12 @@ public class SwitchBootstrapsTest {
|
||||
assertEquals(-1, (int) indy.invoke(null, start));
|
||||
}
|
||||
|
||||
private void testPrimitiveType(Object target, Class<?> targetType, int start, int result, Object... labels) throws Throwable {
|
||||
MethodType switchType = MethodType.methodType(int.class, targetType, int.class);
|
||||
MethodHandle indy = ((CallSite) BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), "", switchType, labels)).dynamicInvoker();
|
||||
assertEquals((int) indy.invoke(target, start), result);
|
||||
}
|
||||
|
||||
private void testEnum(Enum<?> target, int start, int result, Object... labels) throws Throwable {
|
||||
testEnum(target.getClass(), target, start, result, labels);
|
||||
}
|
||||
@ -132,6 +138,18 @@ public class SwitchBootstrapsTest {
|
||||
}, 0, 1, 1L);
|
||||
}
|
||||
|
||||
public void testPrimitiveTypes() throws Throwable {
|
||||
testPrimitiveType((short) 1, short.class, 0, 1, String.class);
|
||||
testPrimitiveType((byte) 1, byte.class,0, 1, String.class, byte.class);
|
||||
testPrimitiveType(true, boolean.class,0, 1, false, boolean.class);
|
||||
testPrimitiveType(1, int.class,0, 1, String.class);
|
||||
testPrimitiveType(1, int.class,0, 1, true);
|
||||
testPrimitiveType(true, boolean.class,0, 1, false);
|
||||
testPrimitiveType((byte) 1, byte.class,0, 1, boolean.class, byte.class);
|
||||
testPrimitiveType((byte) 1, byte.class,0, 1, Boolean.class, byte.class);
|
||||
testPrimitiveType(true, boolean.class,0, 1, String.class, boolean.class);
|
||||
}
|
||||
|
||||
public void testEnums() throws Throwable {
|
||||
testEnum(E1.A, 0, 2, "B", "C", "A", E1.class);
|
||||
testEnum(E1.B, 0, 0, "B", "C", "A", E1.class);
|
||||
|
Loading…
x
Reference in New Issue
Block a user