Skip to content

Commit

Permalink
new(test) Stack validation in CALLF
Browse files Browse the repository at this point in the history
Add a test to cover cases where stack would not overflow but CALLF stack
reservation rules would cause a revert.

Signed-off-by: Danno Ferrin <[email protected]>
  • Loading branch information
shemnon committed Oct 10, 2024
1 parent e6d68b0 commit 7fba9a0
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
2 changes: 2 additions & 0 deletions tests/osaka/eip7692_eof_v1/eip4750_functions/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
next(_slot) # don't use slot 0
slot_code_worked = next(_slot)
slot_last_slot = next(_slot)
slot_stack_canary = next(_slot)

"""Storage values for common testing fields"""
value_code_worked = 0x2015
value_canary_written = 0xDEADB12D
108 changes: 106 additions & 2 deletions tests/osaka/eip7692_eof_v1/eip4750_functions/test_callf_execution.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
"""
EOF CALLF execution tests
"""

import pytest

from ethereum_test_specs import StateTestFiller
from ethereum_test_tools import Account, EOFStateTestFiller
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools.eof.v1 import Container, Section
from ethereum_test_types import Alloc, Environment, Transaction

from .. import EOF_FORK_NAME
from .helpers import slot_code_worked, value_code_worked
from ..eip7620_eof_create.helpers import (
value_canary_should_not_change,
value_canary_to_be_overwritten,
)
from .helpers import slot_code_worked, slot_stack_canary, value_canary_written, value_code_worked

REFERENCE_SPEC_GIT_PATH = "EIPS/eip-4750.md"
REFERENCE_SPEC_VERSION = "14400434e1199c57d912082127b1d22643788d11"
Expand Down Expand Up @@ -252,3 +257,102 @@ def test_callf_with_inputs_stack_overflow(
),
container_post=Account(storage={slot_code_worked: 0}),
)


@pytest.mark.parametrize(
("stack_height", "inputs", "outputs", "failure"),
(
pytest.param(1020, 1, 3, False, id="1020"),
pytest.param(1021, 1, 3, True, id="1021"),
),
)
def test_callf_sneaky_stack_overflow(
stack_height: int,
inputs: int,
outputs: int,
failure: bool,
state_test: StateTestFiller,
pre: Alloc,
):
"""
CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule #3 triggers.

Code Section 0 - Mostly fills the stack
Code Section 1 - jumper to 2, so class verification passes (we want a runtime failure)
Code Section 2 - Could require too much stack, but doesn't as it JUMPFs to 3
Code Section 3 - Writes canary values

The intent is to catch implementations of CALLF that don't enforce rule #3
"""
env = Environment()
sender = pre.fund_eoa()
contract_address = pre.deploy_contract(
code=Container(
sections=[
Section.Code(
code=Op.PUSH0 * stack_height
+ Op.CALLF[1]
+ Op.POP * stack_height
+ Op.SSTORE(slot_code_worked, value_code_worked)
+ Op.RETURN(0, 0),
max_stack_height=stack_height + outputs - inputs,
),
Section.Code(
Op.CALLF[2] + Op.POP + Op.RETF,
code_inputs=inputs,
code_outputs=outputs,
max_stack_height=outputs + 1,
),
Section.Code(
Op.RJUMPI[4]
+ Op.PUSH0
+ Op.JUMPF[3]
+ Op.PUSH0 * (outputs - inputs + 3)
+ Op.POP
+ Op.RETF,
code_inputs=inputs,
code_outputs=outputs + 1,
max_stack_height=outputs + 2,
),
Section.Code(
Op.POP * inputs
+ Op.SSTORE(slot_stack_canary, value_canary_written)
+ Op.PUSH0 * (outputs + 1)
+ Op.RETF,
code_inputs=inputs,
code_outputs=outputs + 1,
max_stack_height=outputs + 1,
),
],
),
storage={
slot_code_worked: (
value_canary_should_not_change if failure else value_canary_to_be_overwritten
),
slot_stack_canary: (
value_canary_should_not_change if failure else value_canary_to_be_overwritten
),
},
)

post = {
contract_address: Account(
storage={
slot_code_worked: (
value_canary_should_not_change if failure else value_code_worked
),
slot_stack_canary: (
value_canary_should_not_change if failure else value_canary_written
),
}
)
}

tx = Transaction(
to=contract_address,
gas_limit=10_000_000,
gas_price=10,
protected=False,
sender=sender,
)
state_test(env=env, pre=pre, post=post, tx=tx)
1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ eip4844
eip6110
eip7002
eip7069
eip7620
eip7692
eip7251
eips
Expand Down

0 comments on commit 7fba9a0

Please sign in to comment.