forked from ethereum/execution-spec-tests
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new(tests): EOF: tests for invalid non-returning sections
Add new EOF validation tests where the a section marked returning/non-returning does not match the reality.
- Loading branch information
Showing
3 changed files
with
115 additions
and
6 deletions.
There are no files selected for viewing
108 changes: 108 additions & 0 deletions
108
tests/prague/eip7692_eof_v1/eip6206_jumpf/test_nonretruning_validation.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
""" | ||
EOF validation tests for non-returning code sections. | ||
""" | ||
|
||
import pytest | ||
|
||
from ethereum_test_tools import EOFException, EOFTestFiller | ||
from ethereum_test_tools.eof.v1 import Container, Section | ||
from ethereum_test_tools.vm.opcode import Opcodes as Op | ||
from ethereum_test_types.eof.v1 import NON_RETURNING_SECTION | ||
from ethereum_test_vm import Bytecode | ||
|
||
from .. import EOF_FORK_NAME | ||
|
||
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6206.md" | ||
REFERENCE_SPEC_VERSION = "2f365ea0cd58faa6e26013ea77ce6d538175f7d0" | ||
|
||
pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"code_section", | ||
[ | ||
pytest.param(Section.Code(Op.STOP, code_outputs=0), id="stop"), | ||
pytest.param(Section.Code(Op.INVALID, code_outputs=0), id="invalid0"), | ||
pytest.param( | ||
Section.Code(Op.ADDRESS + Op.POP + Op.INVALID, code_outputs=0), id="invalid1" | ||
), | ||
pytest.param(Section.Code(Op.RETURN(0, 0), code_outputs=0), id="return"), | ||
pytest.param(Section.Code(Op.RETF, code_outputs=0), id="retf0"), | ||
pytest.param(Section.Code(Op.PUSH0 + Op.RETF, code_outputs=1), id="retf1"), | ||
], | ||
) | ||
def test_first_section_returning(eof_test: EOFTestFiller, code_section: Section): | ||
"""Test EOF validation failing because the first section is not non-returning.""" | ||
eof_test( | ||
data=Container( | ||
sections=[code_section], validity_error=EOFException.INVALID_FIRST_SECTION_TYPE | ||
) | ||
) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"code_section", | ||
[ | ||
pytest.param(Section.Code(Op.RETF, code_outputs=NON_RETURNING_SECTION), id="retf0"), | ||
pytest.param( | ||
Section.Code(Op.PUSH0 + Op.RETF, code_outputs=NON_RETURNING_SECTION), id="retf1" | ||
), | ||
], | ||
) | ||
def test_retf_in_nonreturning(eof_test: EOFTestFiller, code_section: Section): | ||
""" | ||
Test EOF validation failing because a non-returning section contains the RETF instruction. | ||
""" | ||
# TODO: This can be further parametrized to put the offending section as not-first one. | ||
eof_test( | ||
data=Container( | ||
sections=[code_section], validity_error=EOFException.INVALID_NON_RETURNING_FLAG | ||
) | ||
) | ||
|
||
|
||
@pytest.mark.parametrize("first", [True, False]) | ||
@pytest.mark.parametrize("code_prefix", [Bytecode(), Op.PUSH0]) | ||
def test_jumpf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: Bytecode): | ||
""" | ||
Test EOF validation failing because a non-returning section contains the JUMPF instruction. | ||
""" | ||
invalid_section = Section.Code( | ||
code_prefix + Op.JUMPF[1 if first else 2], | ||
code_outputs=NON_RETURNING_SECTION, | ||
) | ||
target_section = Section.Code(Op.RETF) | ||
sections = [invalid_section, target_section] | ||
if not first: # Prefix sections with additional valid JUMPF to invalid section | ||
sections = [Section.Code(Op.JUMPF[1])] + sections | ||
|
||
eof_test( | ||
data=Container( | ||
sections=sections, | ||
validity_error=EOFException.INVALID_NON_RETURNING_FLAG, | ||
) | ||
) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"code_section", | ||
[ | ||
pytest.param(Section.Code(Op.STOP, code_outputs=0), id="stop0"), | ||
pytest.param(Section.Code(Op.PUSH0 + Op.STOP, code_outputs=1), id="stop1"), | ||
pytest.param(Section.Code(Op.INVALID, code_outputs=0), id="invalid0"), | ||
pytest.param(Section.Code(Op.PUSH0 + Op.INVALID, code_outputs=1), id="invalid1"), | ||
], | ||
) | ||
def test_returning_section_not_returning(eof_test: EOFTestFiller, code_section: Section): | ||
""" | ||
Test EOF validation failing because a returning sections ends with non-returning instruction. | ||
""" | ||
eof_test( | ||
data=Container( | ||
sections=[ | ||
Section.Code(Op.CALLF[1] + Op.STOP, max_stack_height=code_section.code_outputs), | ||
code_section, | ||
], | ||
validity_error=EOFException.INVALID_NON_RETURNING_FLAG, | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -263,6 +263,7 @@ nethermind | |
nexternal | ||
nGo | ||
nJSON | ||
nonreturning | ||
nop | ||
NOP | ||
NOPs | ||
|