|
16 | 16 | #include <numeric>
|
17 | 17 | #include <queue>
|
18 | 18 | #include <unordered_set>
|
| 19 | +#include <variant> |
19 | 20 | #include <vector>
|
20 | 21 |
|
21 | 22 | namespace evmone
|
@@ -235,6 +236,74 @@ std::variant<EOFSectionHeaders, EOFValidationError> validate_section_headers(byt
|
235 | 236 | return section_headers;
|
236 | 237 | }
|
237 | 238 |
|
| 239 | +std::variant<EOF1Header, EOFValidationError> validate_header( |
| 240 | + evmc_revision rev, bytes_view container) noexcept |
| 241 | +{ |
| 242 | + if (!is_eof_container(container)) |
| 243 | + return EOFValidationError::invalid_prefix; |
| 244 | + |
| 245 | + const auto version = get_eof_version(container); |
| 246 | + if (version != 1) |
| 247 | + return EOFValidationError::eof_version_unknown; |
| 248 | + |
| 249 | + if (rev < EVMC_OSAKA) |
| 250 | + return EOFValidationError::eof_version_unknown; |
| 251 | + |
| 252 | + // `offset` variable handled below is known to not be greater than the container size, as |
| 253 | + // checked in `validate_section_headers`. Combined with the requirement for the container |
| 254 | + // size to not exceed MAX_INITCODE_SIZE (checked before `validate-header` is called), |
| 255 | + // this allows us to cast `offset` to narrower integers. |
| 256 | + assert(container.size() <= MAX_INITCODE_SIZE); |
| 257 | + |
| 258 | + auto section_headers_or_error = validate_section_headers(container); |
| 259 | + if (const auto* error = std::get_if<EOFValidationError>(§ion_headers_or_error)) |
| 260 | + return *error; |
| 261 | + |
| 262 | + auto& section_headers = std::get<EOFSectionHeaders>(section_headers_or_error); |
| 263 | + |
| 264 | + const auto header_size = eof_header_size(section_headers); |
| 265 | + |
| 266 | + const auto type_section_offset = header_size; |
| 267 | + |
| 268 | + if (section_headers.type_size != |
| 269 | + section_headers.code_sizes.size() * EOF1Header::TYPE_ENTRY_SIZE) |
| 270 | + return EOFValidationError::invalid_type_section_size; |
| 271 | + |
| 272 | + auto offset = header_size + section_headers.type_size; |
| 273 | + |
| 274 | + std::vector<uint16_t> code_offsets; |
| 275 | + code_offsets.reserve(section_headers.code_sizes.size()); |
| 276 | + for (const auto code_size : section_headers.code_sizes) |
| 277 | + { |
| 278 | + assert(offset <= std::numeric_limits<uint16_t>::max()); |
| 279 | + code_offsets.emplace_back(static_cast<uint16_t>(offset)); |
| 280 | + offset += code_size; |
| 281 | + } |
| 282 | + |
| 283 | + std::vector<uint32_t> container_offsets; |
| 284 | + container_offsets.reserve(section_headers.container_sizes.size()); |
| 285 | + for (const auto container_size : section_headers.container_sizes) |
| 286 | + { |
| 287 | + assert(offset <= std::numeric_limits<uint32_t>::max()); |
| 288 | + container_offsets.emplace_back(static_cast<uint32_t>(offset)); |
| 289 | + offset += container_size; |
| 290 | + } |
| 291 | + |
| 292 | + assert(offset <= std::numeric_limits<uint32_t>::max()); |
| 293 | + const auto data_offset = static_cast<uint32_t>(offset); |
| 294 | + |
| 295 | + return EOF1Header{ |
| 296 | + .version = container[2], |
| 297 | + .type_section_offset = type_section_offset, |
| 298 | + .code_sizes = std::move(section_headers.code_sizes), |
| 299 | + .code_offsets = std::move(code_offsets), |
| 300 | + .data_size = section_headers.data_size, |
| 301 | + .data_offset = data_offset, |
| 302 | + .container_sizes = std::move(section_headers.container_sizes), |
| 303 | + .container_offsets = std::move(container_offsets), |
| 304 | + }; |
| 305 | +} |
| 306 | + |
238 | 307 | EOFValidationError validate_types(bytes_view container, const EOF1Header& header) noexcept
|
239 | 308 | {
|
240 | 309 | for (size_t i = 0; i < header.get_type_count(); ++i)
|
@@ -755,74 +824,6 @@ bool is_eof_container(bytes_view container) noexcept
|
755 | 824 | return container.starts_with(EOF_MAGIC);
|
756 | 825 | }
|
757 | 826 |
|
758 |
| -std::variant<EOF1Header, EOFValidationError> validate_header( |
759 |
| - evmc_revision rev, bytes_view container) noexcept |
760 |
| -{ |
761 |
| - if (!is_eof_container(container)) |
762 |
| - return EOFValidationError::invalid_prefix; |
763 |
| - |
764 |
| - const auto version = get_eof_version(container); |
765 |
| - if (version != 1) |
766 |
| - return EOFValidationError::eof_version_unknown; |
767 |
| - |
768 |
| - if (rev < EVMC_OSAKA) |
769 |
| - return EOFValidationError::eof_version_unknown; |
770 |
| - |
771 |
| - // `offset` variable handled below is known to not be greater than the container size, as |
772 |
| - // checked in `validate_section_headers`. Combined with the requirement for the container |
773 |
| - // size to not exceed MAX_INITCODE_SIZE (checked before `validate-header` is called), |
774 |
| - // this allows us to cast `offset` to narrower integers. |
775 |
| - assert(container.size() <= MAX_INITCODE_SIZE); |
776 |
| - |
777 |
| - auto section_headers_or_error = validate_section_headers(container); |
778 |
| - if (const auto* error = std::get_if<EOFValidationError>(§ion_headers_or_error)) |
779 |
| - return *error; |
780 |
| - |
781 |
| - auto& section_headers = std::get<EOFSectionHeaders>(section_headers_or_error); |
782 |
| - |
783 |
| - const auto header_size = eof_header_size(section_headers); |
784 |
| - |
785 |
| - const auto type_section_offset = header_size; |
786 |
| - |
787 |
| - if (section_headers.type_size != |
788 |
| - section_headers.code_sizes.size() * EOF1Header::TYPE_ENTRY_SIZE) |
789 |
| - return EOFValidationError::invalid_type_section_size; |
790 |
| - |
791 |
| - auto offset = header_size + section_headers.type_size; |
792 |
| - |
793 |
| - std::vector<uint16_t> code_offsets; |
794 |
| - code_offsets.reserve(section_headers.code_sizes.size()); |
795 |
| - for (const auto code_size : section_headers.code_sizes) |
796 |
| - { |
797 |
| - assert(offset <= std::numeric_limits<uint16_t>::max()); |
798 |
| - code_offsets.emplace_back(static_cast<uint16_t>(offset)); |
799 |
| - offset += code_size; |
800 |
| - } |
801 |
| - |
802 |
| - std::vector<uint32_t> container_offsets; |
803 |
| - container_offsets.reserve(section_headers.container_sizes.size()); |
804 |
| - for (const auto container_size : section_headers.container_sizes) |
805 |
| - { |
806 |
| - assert(offset <= std::numeric_limits<uint32_t>::max()); |
807 |
| - container_offsets.emplace_back(static_cast<uint32_t>(offset)); |
808 |
| - offset += container_size; |
809 |
| - } |
810 |
| - |
811 |
| - assert(offset <= std::numeric_limits<uint32_t>::max()); |
812 |
| - const auto data_offset = static_cast<uint32_t>(offset); |
813 |
| - |
814 |
| - return EOF1Header{ |
815 |
| - .version = container[2], |
816 |
| - .type_section_offset = type_section_offset, |
817 |
| - .code_sizes = std::move(section_headers.code_sizes), |
818 |
| - .code_offsets = std::move(code_offsets), |
819 |
| - .data_size = section_headers.data_size, |
820 |
| - .data_offset = data_offset, |
821 |
| - .container_sizes = std::move(section_headers.container_sizes), |
822 |
| - .container_offsets = std::move(container_offsets), |
823 |
| - }; |
824 |
| -} |
825 |
| - |
826 | 827 | /// This function expects the prefix and version to be valid, as it ignores it.
|
827 | 828 | EOF1Header read_valid_eof1_header(bytes_view container)
|
828 | 829 | {
|
|
0 commit comments