mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8385114: Prevent creation of invalid TableSwitchInstruction
Reviewed-by: asotona
This commit is contained in:
parent
31596cfef9
commit
05d925ea56
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -3429,6 +3429,9 @@ public sealed interface CodeBuilder
|
||||
* @param defaultTarget the default jump target
|
||||
* @param cases the switch cases
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if the low value is greater than the
|
||||
* high value, or if there are too many targets between the low
|
||||
* and high values
|
||||
* @see Opcode#TABLESWITCH
|
||||
* @see TableSwitchInstruction
|
||||
*/
|
||||
@ -3443,6 +3446,7 @@ public sealed interface CodeBuilder
|
||||
* @param defaultTarget the default jump target
|
||||
* @param cases the switch cases
|
||||
* @return this builder
|
||||
* @throws IllegalArgumentException if {@code cases} is empty
|
||||
* @see Opcode#TABLESWITCH
|
||||
* @see #tableswitch(int, int, Label, List)
|
||||
* @see TableSwitchInstruction
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -95,6 +95,9 @@ public sealed interface TableSwitchInstruction extends Instruction
|
||||
* @param defaultTarget the default target of the switch
|
||||
* @param cases the cases of the switch; duplicate or out of bound case
|
||||
* handling is not specified
|
||||
* @throws IllegalArgumentException if the low value is greater than the
|
||||
* high value, or if there are too many targets between the low
|
||||
* and high values
|
||||
*/
|
||||
static TableSwitchInstruction of(int lowValue, int highValue, Label defaultTarget, List<SwitchCase> cases) {
|
||||
return new AbstractInstruction.UnboundTableSwitchInstruction(lowValue, highValue, defaultTarget, cases);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -289,9 +289,7 @@ public abstract sealed class AbstractInstruction
|
||||
afterPad = code.codeStart + RawBytecodeHelper.align(pos + 1 - code.codeStart);
|
||||
low = code.classReader.readInt(afterPad + 4);
|
||||
high = code.classReader.readInt(afterPad + 8);
|
||||
if (high < low || (long)high - low > code.codeLength >> 2) {
|
||||
throw new IllegalArgumentException("Invalid tableswitch values low: " + low + " high: " + high);
|
||||
}
|
||||
BytecodeHelpers.validateTableSwitchValues(low, high, code.codeLength);
|
||||
int cnt = high - low + 1;
|
||||
size = afterPad + 12 + cnt * 4 - pos;
|
||||
}
|
||||
@ -926,6 +924,7 @@ public abstract sealed class AbstractInstruction
|
||||
|
||||
public UnboundTableSwitchInstruction(int lowValue, int highValue, Label defaultTarget, List<SwitchCase> cases) {
|
||||
super(Opcode.TABLESWITCH);
|
||||
BytecodeHelpers.validateTableSwitchValues(lowValue, highValue);
|
||||
this.lowValue = lowValue;
|
||||
this.highValue = highValue;
|
||||
this.defaultTarget = requireNonNull(defaultTarget);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -484,6 +484,16 @@ public class BytecodeHelpers {
|
||||
.concat(Long.toString(value)));
|
||||
}
|
||||
|
||||
public static void validateTableSwitchValues(int low, int high) {
|
||||
validateTableSwitchValues(low, high, 0xFFFF);
|
||||
}
|
||||
|
||||
public static void validateTableSwitchValues(int low, int high, int codeLength) {
|
||||
if (high < low || 1L + high - low > codeLength >> 2) {
|
||||
throw new IllegalArgumentException("Invalid tableswitch values low: " + low + " high: " + high);
|
||||
}
|
||||
}
|
||||
|
||||
public static MethodHandleEntry handleDescToHandleInfo(ConstantPoolBuilder constantPool, DirectMethodHandleDesc bootstrapMethod) {
|
||||
ClassEntry bsOwner = constantPool.classEntry(bootstrapMethod.owner());
|
||||
NameAndTypeEntry bsNameAndType = constantPool.nameAndTypeEntry(constantPool.utf8Entry(bootstrapMethod.methodName()),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -1859,6 +1859,7 @@ public final class DirectCodeBuilder
|
||||
|
||||
@Override
|
||||
public CodeBuilder tableswitch(int low, int high, Label defaultTarget, List<SwitchCase> cases) {
|
||||
BytecodeHelpers.validateTableSwitchValues(low, high);
|
||||
Objects.requireNonNull(defaultTarget);
|
||||
// check cases when we write them
|
||||
writeTableSwitch(low, high, defaultTarget, cases);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8341277 8361102 8361182 8361614
|
||||
* @bug 8341277 8361102 8361182 8361614 8385114
|
||||
* @summary Testing ClassFile (pseudo-)instruction argument validation.
|
||||
* @run junit InstructionValidationTest
|
||||
*/
|
||||
@ -94,15 +94,44 @@ class InstructionValidationTest {
|
||||
@Test
|
||||
void testSwitch() {
|
||||
TestUtil.runCodeHandler(cob -> {
|
||||
// Null labels/cases
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(null, List.of(SwitchCase.of(1, cob.startLabel()))));
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(cob.startLabel(), null));
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(cob.startLabel(), Collections.singletonList(null)));
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, cob.startLabel(), null));
|
||||
assertThrows(NullPointerException.class, () -> cob.lookupswitch(cob.startLabel(), null));
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, cob.startLabel(), Collections.singletonList(null)));
|
||||
assertThrows(NullPointerException.class, () -> cob.lookupswitch(cob.startLabel(), Collections.singletonList(null)));
|
||||
assertThrows(NullPointerException.class, () -> cob.tableswitch(-1, 1, null, List.of()));
|
||||
assertThrows(NullPointerException.class, () -> cob.lookupswitch(null, List.of()));
|
||||
// Illegal start/end
|
||||
assertThrows(IllegalArgumentException.class, () -> cob.tableswitch(cob.startLabel(), List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> cob.tableswitch(1, -1, cob.startLabel(), List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> cob.tableswitch(Integer.MAX_VALUE, Integer.MIN_VALUE, cob.startLabel(), List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> cob.tableswitch(1, 16384, cob.startLabel(), List.of()));
|
||||
// Ensures nothing redundant is written in case of failure
|
||||
cob.return_();
|
||||
});
|
||||
|
||||
Label[] capture = new Label[1];
|
||||
ClassFile.of().build(CD_Object, clb -> clb.withMethodBody("test", MTD_void, 0, cob -> {
|
||||
capture[0] = cob.startLabel();
|
||||
cob.return_();
|
||||
}));
|
||||
Label dummyLabel = capture[0];
|
||||
assertNotNull(dummyLabel);
|
||||
|
||||
TableSwitchInstruction.of(0, 0, dummyLabel, List.of());
|
||||
LookupSwitchInstruction.of(dummyLabel, List.of());
|
||||
assertThrows(NullPointerException.class, () -> TableSwitchInstruction.of(0, 0, dummyLabel, null));
|
||||
assertThrows(NullPointerException.class, () -> LookupSwitchInstruction.of(dummyLabel, null));
|
||||
assertThrows(NullPointerException.class, () -> TableSwitchInstruction.of(0, 0, dummyLabel, Collections.singletonList(null)));
|
||||
assertThrows(NullPointerException.class, () -> LookupSwitchInstruction.of(dummyLabel, Collections.singletonList(null)));
|
||||
assertThrows(NullPointerException.class, () -> TableSwitchInstruction.of(0, 0, null, List.of()));
|
||||
assertThrows(NullPointerException.class, () -> LookupSwitchInstruction.of(null, List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> TableSwitchInstruction.of(1, -1, dummyLabel, List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> TableSwitchInstruction.of(Integer.MAX_VALUE, Integer.MIN_VALUE, dummyLabel, List.of()));
|
||||
assertThrows(IllegalArgumentException.class, () -> TableSwitchInstruction.of(1, 16384, dummyLabel, List.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user