RFR: 8354323: Safeguard SwitchBootstraps.typeSwitch when used outside the compiler

Aggelos Biboudis abimpoudis at openjdk.org
Wed May 7 18:30:59 UTC 2025


On Wed, 7 May 2025 16:36:09 GMT, Chen Liang <liach at openjdk.org> wrote:

>> While the compiler does not allow invalid queries to flow into `SwitchBootstraps:typeSwitch`, a library user could do that and `typeSwitch` does not prevent such usage pattern errors resulting in erroneous evaluation.
>> 
>> For example this is not valid Java (and protected) by javac:
>> 
>> 
>> byte b = 1;
>> switch (b) {
>>     case String s -> System.out.println("How did we get here? byte is " + s.getClass());
>> }
>> 
>> 
>> but this is a valid call (and not protected):
>> 
>> 
>> CallSite shortSwitch = SwitchBootstraps.typeSwitch(
>>     MethodHandles.lookup(), 
>>     "", 
>>     MethodType.methodType(int.class, short.class, int.class),  // models (short, int) -> int
>>     String.class);
>> 
>> 
>> The `SwitchBootstraps.typeSwitch` returns wrong result since the code was reasoning erroneously that this pair was unconditionally exact. 
>> 
>> This PR proposes to add the safety check in unconditional exactness which will return false in erroneous pairs and then the actual check will be delegated to `instanceof`. For the case of erroneous pairs with primitive `boolean`s there is a check in the beginning of the type switch skeleton.
>
> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 553:
> 
>> 551:                         continue;
>> 552:                     }
>> 553:                     else if (unconditionalExactnessCheck(selectorType, classLabel)) {
> 
> Can we merge this into `isNotValidPair(...) || unconditionalExactnessCheck(...)` then do nothing? The next label is already in theory immediately bound to the instruction after goto.

The empty body means that we unconditionally return the index `case 0 -> /*no if is generated*/ return 0;`.

I confirmed that by merging, the following test would not pass. It returns erroneously 0, instead of 1.


testPrimitiveType((byte) 1, byte.class,0, 1, boolean.class, byte.class);

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/25090#discussion_r2078206536


More information about the core-libs-dev mailing list