Skip to content

Commit c0665ef

Browse files
committed
8354323: Safeguard SwitchBootstraps.typeSwitch when used outside the compiler
Reviewed-by: jlahoda, liach
1 parent 85b24c3 commit c0665ef

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,11 @@ private static Consumer<CodeBuilder> generateTypeSwitchSkeleton(Class<?> selecto
546546
Object caseLabel = caseLabels[idx];
547547
cb.labelBinding(caseTargets[idx]);
548548
if (caseLabel instanceof Class<?> classLabel) {
549-
if (unconditionalExactnessCheck(selectorType, classLabel)) {
549+
if (isNotValidPair(selectorType, caseLabel)){
550+
cb.goto_(next);
551+
continue;
552+
}
553+
else if (unconditionalExactnessCheck(selectorType, classLabel)) {
550554
//nothing - unconditionally use this case
551555
} else if (classLabel.isPrimitive()) {
552556
if (!selectorType.isPrimitive() && !Wrapper.isWrapperNumericOrBooleanType(selectorType)) {
@@ -717,6 +721,11 @@ private static Consumer<CodeBuilder> generateTypeSwitchSkeleton(Class<?> selecto
717721
};
718722
}
719723

724+
private static boolean isNotValidPair(Class<?> selectorType, Object caseLabel) {
725+
return (selectorType == boolean.class && caseLabel != boolean.class && caseLabel != Boolean.class) ||
726+
(selectorType != boolean.class && selectorType.isPrimitive() && (caseLabel == boolean.class || caseLabel == Boolean.class));
727+
}
728+
720729
/*
721730
* Construct the method handle that represents the method int typeSwitch(Object, int, BiPredicate, List)
722731
*/
@@ -769,11 +778,11 @@ private static boolean unconditionalExactnessCheck(Class<?> selectorType, Class<
769778
return true;
770779
}
771780
else if (selectorType.equals(targetType) ||
772-
((selectorType.equals(byte.class) && !targetType.equals(char.class)) ||
773-
(selectorType.equals(short.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) ||
774-
(selectorType.equals(char.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))) ||
775-
(selectorType.equals(int.class) && (targetType.equals(double.class) || targetType.equals(long.class))) ||
776-
(selectorType.equals(float.class) && (selectorWrapper.isStrictSubRangeOf(targetWrapper))))) return true;
781+
(targetType.isPrimitive() && selectorType.isPrimitive() &&
782+
(selectorWrapper.isStrictSubRangeOf(targetWrapper) &&
783+
!((selectorType.equals(byte.class) && targetType.equals(char.class)) ||
784+
(selectorType.equals(int.class) && targetType.equals(float.class)) ||
785+
(selectorType.equals(long.class) && (targetType.equals(double.class) || targetType.equals(float.class))))))) return true;
777786
return false;
778787
}
779788

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5085,16 +5085,12 @@ public boolean isUnconditionallyExact(Type source, Type target) {
50855085
* @param targetType Target type
50865086
*/
50875087
public boolean isUnconditionallyExactPrimitives(Type selectorType, Type targetType) {
5088-
if (isSameType(selectorType, targetType)) {
5089-
return true;
5090-
}
5091-
5092-
return (selectorType.isPrimitive() && targetType.isPrimitive()) &&
5093-
((selectorType.hasTag(BYTE) && !targetType.hasTag(CHAR)) ||
5094-
(selectorType.hasTag(SHORT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) ||
5095-
(selectorType.hasTag(CHAR) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))) ||
5096-
(selectorType.hasTag(INT) && (targetType.hasTag(DOUBLE) || targetType.hasTag(LONG))) ||
5097-
(selectorType.hasTag(FLOAT) && (selectorType.getTag().isStrictSubRangeOf(targetType.getTag()))));
5088+
return isSameType(selectorType, targetType) ||
5089+
(selectorType.isPrimitive() && targetType.isPrimitive()) &&
5090+
((selectorType.getTag().isStrictSubRangeOf(targetType.getTag())) &&
5091+
!((selectorType.hasTag(BYTE) && targetType.hasTag(CHAR)) ||
5092+
(selectorType.hasTag(INT) && targetType.hasTag(FLOAT)) ||
5093+
(selectorType.hasTag(LONG) && (targetType.hasTag(DOUBLE) || targetType.hasTag(FLOAT)))));
50985094
}
50995095
// </editor-fold>
51005096

test/jdk/java/lang/runtime/SwitchBootstrapsTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ private void testType(Object target, int start, int result, Object... labels) th
7474
assertEquals(-1, (int) indy.invoke(null, start));
7575
}
7676

77+
private void testPrimitiveType(Object target, Class<?> targetType, int start, int result, Object... labels) throws Throwable {
78+
MethodType switchType = MethodType.methodType(int.class, targetType, int.class);
79+
MethodHandle indy = ((CallSite) BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), "", switchType, labels)).dynamicInvoker();
80+
assertEquals((int) indy.invoke(target, start), result);
81+
}
82+
7783
private void testEnum(Enum<?> target, int start, int result, Object... labels) throws Throwable {
7884
testEnum(target.getClass(), target, start, result, labels);
7985
}
@@ -132,6 +138,18 @@ public boolean equals(Object obj) {
132138
}, 0, 1, 1L);
133139
}
134140

141+
public void testPrimitiveTypes() throws Throwable {
142+
testPrimitiveType((short) 1, short.class, 0, 1, String.class);
143+
testPrimitiveType((byte) 1, byte.class,0, 1, String.class, byte.class);
144+
testPrimitiveType(true, boolean.class,0, 1, false, boolean.class);
145+
testPrimitiveType(1, int.class,0, 1, String.class);
146+
testPrimitiveType(1, int.class,0, 1, true);
147+
testPrimitiveType(true, boolean.class,0, 1, false);
148+
testPrimitiveType((byte) 1, byte.class,0, 1, boolean.class, byte.class);
149+
testPrimitiveType((byte) 1, byte.class,0, 1, Boolean.class, byte.class);
150+
testPrimitiveType(true, boolean.class,0, 1, String.class, boolean.class);
151+
}
152+
135153
public void testEnums() throws Throwable {
136154
testEnum(E1.A, 0, 2, "B", "C", "A", E1.class);
137155
testEnum(E1.B, 0, 0, "B", "C", "A", E1.class);

0 commit comments

Comments
 (0)