Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new(tests): EOF validation of opcodes #932

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

chfast
Copy link
Member

@chfast chfast commented Oct 31, 2024

🗒️ Description

Add missing opcode tests:

  • invalid opcode placed after a STOP instruction,
  • PUSH opcodes with truncated immediate bytes.

Mark rest of the "opcode tests" as done by providing links to tests.

✅ Checklist

@chfast chfast added scope:tests Scope: Test cases type:test Type: Test labels Oct 31, 2024
Copy link
Collaborator

@pdobacz pdobacz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, can go as is, but I had a couple of comments/ideas

"""
Test that an invalid opcode placed after STOP (terminating instruction) invalidates EOF.
"""
eof_code = Container(sections=[Section.Code(code=Op.STOP + opcode), Section.Data("00" * 32)])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be parametrized with all terminating instructions and an RJUMP[-3] too

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

sorted(push_opcodes),
)
@pytest.mark.parametrize(
"any_imm",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any_imm name threw me off the scent. Maybe "truncate_whole" ("truncate_one_byte") verbosely

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the risk of test bloat, should we test all lengths within a push? It's over 500 tests but super easy to code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the risk of test bloat, should we test all lengths within a push? It's over 500 tests but super easy to code.

I'd say pass to this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this particular combo of 2 tests begs to add 3rd test combining them: a truncated push after a terminating instr? Or is it too much?

eof_code = Container(sections=[Section.Code(code=Op.STOP + opcode), Section.Data("00" * 32)])
eof_test(
data=eof_code,
expect_exception=EOFException.UNDEFINED_INSTRUCTION,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we want to add this preemptively, but some impls could fail with UNREACHABLE_CODE and still make sense. But maybe better to keep simple, it is quite likely that instruction definedness is checked first.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible to define a list of possible exceptions

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a combined loop it makes sense to check if the code has been forward referenced before decoding the opcode. So it could easily be unreachable.

Which begs the question, should we test for all opcodes after a STOP, not just invalid ones? Is this a code reachability issue or a opcode validity issue?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally read it as an opcode validity issue, unreachability is added as noise to confuse the eof. But it could be ofc generalized to a reachability issue, with opcode validity as a parameter. It depends on whether and where we have unreachable valid opcodes tested

@marioevz
Copy link
Member

marioevz commented Nov 1, 2024

Created ipsilon#4 with a suggestion, let me know if the changes look good to you.

chfast and others added 4 commits November 5, 2024 14:21
Add missing opcode tests:
- invalid opcode placed after a STOP instruction,
- PUSH opcodes with truncated immediate bytes.

Mark rest of the "opcode tests" as done by providing links to tests.
@chfast chfast force-pushed the eof/migrate_opcode_validation branch from 3d305f0 to 98d3b74 Compare November 5, 2024 13:33
opcode_with_data_portion: bytes = bytes(opcode[1])

if len(opcode_with_data_portion) == 2 and trunc_all:
pytest.skip("can only be truncated one-way")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the use of pytest.skip is good here. We want to exclude some combination of parameters but don't want to print skip logs for these tests.

tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_CALLF] SKIPPED (max_stack_height is 0)                                         [916/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_JUMPF] SKIPPED (max_stack_height is 0)                                         [917/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_DUPN] SKIPPED (can only be truncated one-way)                                  [918/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_SWAPN] SKIPPED (can only be truncated one-way)                                 [919/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_EXCHANGE] SKIPPED (can only be truncated one-way)                              [920/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_EOFCREATE] SKIPPED (can only be truncated one-way)                             [921/922]
tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py::test_truncated_data_portion_opcodes[fork_Osaka-eof_test-compute_max_stack_height_True-trunc_all_True-opcode_RETURNCONTRACT] SKIPPED (can only be truncated one-way)                        [922/922]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope:tests Scope: Test cases type:test Type: Test
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants