diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/RelativeJumpVectorOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/RelativeJumpVectorOperation.java index 54c144d487..bf5642aa15 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/RelativeJumpVectorOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/RelativeJumpVectorOperation.java @@ -41,7 +41,15 @@ public class RelativeJumpVectorOperation extends AbstractFixedCostOperation { @Override protected OperationResult executeFixedCostOperation(final MessageFrame frame, final EVM evm) { final Bytes code = frame.getCode().getBytes(); - final int offsetCase = frame.popStackItem().toInt(); + int offsetCase; + try { + offsetCase = frame.popStackItem().toInt(); + if (offsetCase < 0) { + offsetCase = Integer.MAX_VALUE; + } + } catch (ArithmeticException | IllegalArgumentException ae) { + offsetCase = Integer.MAX_VALUE; + } final int vectorSize = getVectorSize(code, frame.getPC() + 1); return new OperationResult( gasCost, diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java index 69aebfae95..e4aeea887a 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/RelativeJumpOperationTest.java @@ -129,6 +129,87 @@ class RelativeJumpOperationTest { assertThat(rjumpResult.getPcIncrement()).isEqualTo(1 + 2 * jumpVectorSize + 1); } + @ParameterizedTest + @ValueSource( + strings = { + "0xff", + "0x5f5f", + "0xf5f5", + "0x7fff", + "0xffff", + "0x5f5f5f5f", + "0xf5f5f5f5", + "0x7fffffff", + "0xffffffff", + "0x5f5f5f5f5f5f5f5f", + "0xf5f5f5f5f5f5f5f5", + "0x7fffffffffffffff", + "0xffffffffffffffff", + "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f", + "0xf5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5", + "0x7fffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffff", + "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f", + "0xf5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5", + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }) + void rjumpvOverflowOperation(final String stackValue) { + final GasCalculator gasCalculator = mock(GasCalculator.class); + final Code mockCode = mock(Code.class); + final int rjumpOperationIndex = 3; + final int jumpVectorSize = 255; + final int jumpLength = 400; + final Bytes code = + Bytes.fromHexString( + "00".repeat(rjumpOperationIndex) + + String.format("5e%02x", jumpVectorSize) + + String.format("%04x", jumpLength).repeat(jumpVectorSize)); + + when(mockCode.getBytes()).thenReturn(code); + RelativeJumpVectorOperation rjumpv = new RelativeJumpVectorOperation(gasCalculator); + MessageFrame messageFrame = + new TestMessageFrameBuilder() + .code(mockCode) + .pc(rjumpOperationIndex) + .initialGas(5L) + .pushStackItem(Bytes.fromHexString(stackValue)) + .build(); + + Operation.OperationResult rjumpResult = rjumpv.execute(messageFrame, null); + + assertThat(rjumpResult.getPcIncrement()).isEqualTo(1 + 2 * jumpVectorSize + 1); + } + + @ParameterizedTest + @ValueSource(strings = {"0x7f", "0xf5", "0x5f", "0xfe"}) + void rjumpvIndexOperation(final String stackValue) { + final GasCalculator gasCalculator = mock(GasCalculator.class); + final Code mockCode = mock(Code.class); + final int rjumpOperationIndex = 3; + final int jumpVectorSize = 255; + final int jumpLength = 400; + final Bytes code = + Bytes.fromHexString( + "00".repeat(rjumpOperationIndex) + + String.format("5e%02x", jumpVectorSize) + + String.format("%04x", jumpLength).repeat(jumpVectorSize)); + + when(mockCode.getBytes()).thenReturn(code); + RelativeJumpVectorOperation rjumpv = new RelativeJumpVectorOperation(gasCalculator); + MessageFrame messageFrame = + new TestMessageFrameBuilder() + .code(mockCode) + .pc(rjumpOperationIndex) + .initialGas(5L) + .pushStackItem(Bytes.fromHexString(stackValue)) + .build(); + + Operation.OperationResult rjumpResult = rjumpv.execute(messageFrame, null); + + assertThat(rjumpResult.getPcIncrement()).isEqualTo(2 + 2 * jumpVectorSize + jumpLength); + } + @Test void rjumpvHitOperation() { final GasCalculator gasCalculator = mock(GasCalculator.class);