Skip to content

Commit 8c4c6c4

Browse files
gumb0axic
andcommitted
eof: Change handling of errors from pair<val, err> to variant<val, err>
This helps to reduce stack usage of large functions like validate_eof_headers(). Co-authored-by: Alex Beregszaszi <[email protected]>
1 parent 09851dd commit 8c4c6c4

File tree

1 file changed

+27
-19
lines changed

1 file changed

+27
-19
lines changed

lib/evmone/eof.cpp

+27-19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <array>
99
#include <cassert>
1010
#include <limits>
11+
#include <variant>
1112

1213
namespace evmone
1314
{
@@ -21,7 +22,8 @@ constexpr uint8_t MAX_SECTION = DATA_SECTION;
2122

2223
using EOFSectionHeaders = std::array<uint16_t, MAX_SECTION + 1>;
2324

24-
std::pair<EOFSectionHeaders, EOFValidationError> validate_eof_headers(bytes_view container) noexcept
25+
std::variant<EOFSectionHeaders, EOFValidationError> validate_eof_headers(
26+
bytes_view container) noexcept
2527
{
2628
enum class State
2729
{
@@ -46,54 +48,54 @@ std::pair<EOFSectionHeaders, EOFValidationError> validate_eof_headers(bytes_view
4648
{
4749
case TERMINATOR:
4850
if (section_headers[CODE_SECTION] == 0)
49-
return {{}, EOFValidationError::code_section_missing};
51+
return EOFValidationError::code_section_missing;
5052
state = State::terminated;
5153
break;
5254
case DATA_SECTION:
5355
if (section_headers[CODE_SECTION] == 0)
54-
return {{}, EOFValidationError::code_section_missing};
56+
return EOFValidationError::code_section_missing;
5557
if (section_headers[DATA_SECTION] != 0)
56-
return {{}, EOFValidationError::multiple_data_sections};
58+
return EOFValidationError::multiple_data_sections;
5759
state = State::section_size;
5860
break;
5961
case CODE_SECTION:
6062
if (section_headers[CODE_SECTION] != 0)
61-
return {{}, EOFValidationError::multiple_code_sections};
63+
return EOFValidationError::multiple_code_sections;
6264
state = State::section_size;
6365
break;
6466
default:
65-
return {{}, EOFValidationError::unknown_section_id};
67+
return EOFValidationError::unknown_section_id;
6668
}
6769
break;
6870
}
6971
case State::section_size:
7072
{
7173
const auto size_hi = *it++;
7274
if (it == container_end)
73-
return {{}, EOFValidationError::incomplete_section_size};
75+
return EOFValidationError::incomplete_section_size;
7476
const auto size_lo = *it++;
7577
const auto section_size = static_cast<uint16_t>((size_hi << 8) | size_lo);
7678
if (section_size == 0)
77-
return {{}, EOFValidationError::zero_section_size};
79+
return EOFValidationError::zero_section_size;
7880

7981
section_headers[section_id] = section_size;
8082
state = State::section_id;
8183
break;
8284
}
8385
case State::terminated:
84-
return {{}, EOFValidationError::impossible};
86+
return EOFValidationError::impossible;
8587
}
8688
}
8789

8890
if (state != State::terminated)
89-
return {{}, EOFValidationError::section_headers_not_terminated};
91+
return EOFValidationError::section_headers_not_terminated;
9092

9193
const auto section_bodies_size = section_headers[CODE_SECTION] + section_headers[DATA_SECTION];
9294
const auto remaining_container_size = container_end - it;
9395
if (section_bodies_size != remaining_container_size)
94-
return {{}, EOFValidationError::invalid_section_bodies_size};
96+
return EOFValidationError::invalid_section_bodies_size;
9597

96-
return {section_headers, EOFValidationError::success};
98+
return section_headers;
9799
}
98100

99101
EOFValidationError validate_instructions(evmc_revision rev, bytes_view code) noexcept
@@ -119,21 +121,22 @@ EOFValidationError validate_instructions(evmc_revision rev, bytes_view code) noe
119121
return EOFValidationError::success;
120122
}
121123

122-
std::pair<EOF1Header, EOFValidationError> validate_eof1(
124+
std::variant<EOF1Header, EOFValidationError> validate_eof1(
123125
evmc_revision rev, bytes_view container) noexcept
124126
{
125-
const auto [section_headers, error_header] = validate_eof_headers(container);
126-
if (error_header != EOFValidationError::success)
127-
return {{}, error_header};
127+
const auto section_headers_or_error = validate_eof_headers(container);
128+
if (const auto* error = std::get_if<EOFValidationError>(&section_headers_or_error))
129+
return *error;
128130

131+
const auto& section_headers = std::get<EOFSectionHeaders>(section_headers_or_error);
129132
EOF1Header header{section_headers[CODE_SECTION], section_headers[DATA_SECTION]};
130133

131134
const auto error_instr =
132135
validate_instructions(rev, {&container[header.code_begin()], header.code_size});
133136
if (error_instr != EOFValidationError::success)
134-
return {{}, error_instr};
137+
return error_instr;
135138

136-
return {header, EOFValidationError::success};
139+
return header;
137140
}
138141

139142
} // namespace
@@ -186,7 +189,12 @@ EOFValidationError validate_eof(evmc_revision rev, bytes_view container) noexcep
186189
{
187190
if (rev < EVMC_CANCUN)
188191
return EOFValidationError::eof_version_unknown;
189-
return validate_eof1(rev, container).second;
192+
193+
const auto header_or_error = validate_eof1(rev, container);
194+
if (const auto* error = std::get_if<EOFValidationError>(&header_or_error))
195+
return *error;
196+
else
197+
return EOFValidationError::success;
190198
}
191199
else
192200
return EOFValidationError::eof_version_unknown;

0 commit comments

Comments
 (0)