9
9
10
10
#include < intx/intx.hpp>
11
11
#include < algorithm>
12
- #include < array>
13
12
#include < cassert>
14
13
#include < limits>
15
14
#include < numeric>
16
15
#include < ostream>
17
16
#include < queue>
18
17
#include < span>
19
18
#include < stack>
20
- #include < variant>
21
19
#include < vector>
22
20
23
21
namespace evmone
24
22
{
25
23
namespace
26
24
{
27
- constexpr uint8_t MAGIC[] = {0xef , 0x00 };
28
- constexpr uint8_t TERMINATOR = 0x00 ;
29
- constexpr uint8_t TYPE_SECTION = 0x01 ;
30
- constexpr uint8_t CODE_SECTION = 0x02 ;
31
- constexpr uint8_t CONTAINER_SECTION = 0x03 ;
32
- constexpr uint8_t DATA_SECTION = 0x04 ;
33
- constexpr uint8_t MAX_SECTION = DATA_SECTION;
34
25
constexpr auto CODE_SECTION_NUMBER_LIMIT = 1024 ;
35
26
constexpr auto CONTAINER_SECTION_NUMBER_LIMIT = 256 ;
36
27
constexpr auto MAX_STACK_HEIGHT = 0x03FF ;
@@ -39,8 +30,6 @@ constexpr auto REL_OFFSET_SIZE = sizeof(int16_t);
39
30
constexpr auto STACK_SIZE_LIMIT = 1024 ;
40
31
constexpr uint8_t NON_RETURNING_FUNCTION = 0x80 ;
41
32
42
- using EOFSectionHeaders = std::array<std::vector<uint16_t >, MAX_SECTION + 1 >;
43
-
44
33
size_t eof_header_size (const EOFSectionHeaders& headers) noexcept
45
34
{
46
35
const auto non_code_section_count = 2 ; // type section and data section
@@ -79,140 +68,6 @@ EOFValidationError get_section_missing_error(uint8_t section_id) noexcept
79
68
}
80
69
}
81
70
82
- std::variant<EOFSectionHeaders, EOFValidationError> validate_section_headers (bytes_view container)
83
- {
84
- enum class State
85
- {
86
- section_id,
87
- section_size,
88
- terminated
89
- };
90
-
91
- auto state = State::section_id;
92
- uint8_t section_id = 0 ;
93
- uint16_t section_num = 0 ;
94
- EOFSectionHeaders section_headers{};
95
- const auto container_end = container.end ();
96
- auto it = container.begin () + std::size (MAGIC) + 1 ; // MAGIC + VERSION
97
- uint8_t expected_section_id = TYPE_SECTION;
98
- while (it != container_end && state != State::terminated)
99
- {
100
- switch (state)
101
- {
102
- case State::section_id:
103
- {
104
- section_id = *it++;
105
-
106
- // If DATA_SECTION is expected, CONTAINER_SECTION is also allowed, because
107
- // container section is optional.
108
- if (section_id != expected_section_id &&
109
- (expected_section_id != DATA_SECTION || section_id != CONTAINER_SECTION))
110
- return get_section_missing_error (expected_section_id);
111
-
112
- switch (section_id)
113
- {
114
- case TERMINATOR:
115
- state = State::terminated;
116
- break ;
117
- case TYPE_SECTION:
118
- expected_section_id = CODE_SECTION;
119
- state = State::section_size;
120
- break ;
121
- case CODE_SECTION:
122
- {
123
- if (it >= container_end - 1 )
124
- return EOFValidationError::incomplete_section_number;
125
- section_num = read_uint16_be (it);
126
- it += 2 ;
127
- if (section_num == 0 )
128
- return EOFValidationError::zero_section_size;
129
- if (section_num > CODE_SECTION_NUMBER_LIMIT)
130
- return EOFValidationError::too_many_code_sections;
131
- expected_section_id = DATA_SECTION;
132
- state = State::section_size;
133
- break ;
134
- }
135
- case DATA_SECTION:
136
- expected_section_id = TERMINATOR;
137
- state = State::section_size;
138
- break ;
139
- case CONTAINER_SECTION:
140
- {
141
- if (it >= container_end - 1 )
142
- return EOFValidationError::incomplete_section_number;
143
- section_num = read_uint16_be (it);
144
- it += 2 ;
145
- if (section_num == 0 )
146
- return EOFValidationError::zero_section_size;
147
- if (section_num > CONTAINER_SECTION_NUMBER_LIMIT)
148
- return EOFValidationError::too_many_container_sections;
149
- expected_section_id = DATA_SECTION;
150
- state = State::section_size;
151
- break ;
152
- }
153
- default :
154
- assert (false );
155
- }
156
- break ;
157
- }
158
- case State::section_size:
159
- {
160
- if (section_id == CODE_SECTION || section_id == CONTAINER_SECTION)
161
- {
162
- assert (section_num > 0 ); // Guaranteed by previous validation step.
163
- for (size_t i = 0 ; i < section_num; ++i)
164
- {
165
- if (it >= container_end - 1 )
166
- return EOFValidationError::incomplete_section_size;
167
- const auto section_size = read_uint16_be (it);
168
- it += 2 ;
169
- if (section_size == 0 )
170
- return EOFValidationError::zero_section_size;
171
-
172
- section_headers[section_id].emplace_back (section_size);
173
- }
174
- }
175
- else // TYPES_SECTION or DATA_SECTION
176
- {
177
- if (it >= container_end - 1 )
178
- return EOFValidationError::incomplete_section_size;
179
- const auto section_size = read_uint16_be (it);
180
- it += 2 ;
181
- if (section_size == 0 && section_id != DATA_SECTION)
182
- return EOFValidationError::zero_section_size;
183
-
184
- section_headers[section_id].emplace_back (section_size);
185
- }
186
-
187
- state = State::section_id;
188
- break ;
189
- }
190
- case State::terminated:
191
- return EOFValidationError::impossible;
192
- }
193
- }
194
-
195
- if (state != State::terminated)
196
- return EOFValidationError::section_headers_not_terminated;
197
-
198
- const auto section_bodies_without_data =
199
- section_headers[TYPE_SECTION].front () +
200
- std::accumulate (
201
- section_headers[CODE_SECTION].begin (), section_headers[CODE_SECTION].end (), 0 ) +
202
- std::accumulate (section_headers[CONTAINER_SECTION].begin (),
203
- section_headers[CONTAINER_SECTION].end (), 0 );
204
- const auto remaining_container_size = container_end - it;
205
- // Only data section may be truncated, so remaining_container size must be at least
206
- // declared_size_without_data
207
- if (remaining_container_size < section_bodies_without_data)
208
- return EOFValidationError::invalid_section_bodies_size;
209
-
210
- if (section_headers[TYPE_SECTION][0 ] != section_headers[CODE_SECTION].size () * 4 )
211
- return EOFValidationError::invalid_type_section_size;
212
-
213
- return section_headers;
214
- }
215
-
216
71
std::variant<std::vector<EOFCodeType>, EOFValidationError> validate_types (
217
72
bytes_view container, size_t header_size, uint16_t type_section_size) noexcept
218
73
{
@@ -294,6 +149,9 @@ std::variant<EOF1Header, EOFValidationError> validate_header(
294
149
}
295
150
const auto data_offset = static_cast <uint16_t >(offset);
296
151
152
+ if (container.size () > offset + data_size)
153
+ return EOFValidationError::invalid_section_bodies_size;
154
+
297
155
return EOF1Header{
298
156
.version = container[2 ],
299
157
.code_sizes = code_sizes,
@@ -656,9 +514,6 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
656
514
657
515
auto & subcont_header = std::get<EOF1Header>(error_subcont_or_header);
658
516
659
- if (subcont_header.has_stray_bytes (subcontainer.size ()))
660
- return EOFValidationError::stray_bytes_subcontainer;
661
-
662
517
subcontainer_data_offsets.push_back (subcont_header.data_offset );
663
518
subcontainer_data_sizes.push_back (subcont_header.data_size );
664
519
@@ -728,6 +583,141 @@ bool is_eof_container(bytes_view container) noexcept
728
583
return container.size () > 1 && container[0 ] == MAGIC[0 ] && container[1 ] == MAGIC[1 ];
729
584
}
730
585
586
+ std::variant<EOFSectionHeaders, EOFValidationError> validate_section_headers (
587
+ bytes_view container) noexcept
588
+ {
589
+ enum class State
590
+ {
591
+ section_id,
592
+ section_size,
593
+ terminated
594
+ };
595
+
596
+ auto state = State::section_id;
597
+ uint8_t section_id = 0 ;
598
+ uint16_t section_num = 0 ;
599
+ EOFSectionHeaders section_headers{};
600
+ const auto container_end = container.end ();
601
+ auto it = container.begin () + std::size (MAGIC) + 1 ; // MAGIC + VERSION
602
+ uint8_t expected_section_id = TYPE_SECTION;
603
+ while (it != container_end && state != State::terminated)
604
+ {
605
+ switch (state)
606
+ {
607
+ case State::section_id:
608
+ {
609
+ section_id = *it++;
610
+
611
+ // If DATA_SECTION is expected, CONTAINER_SECTION is also allowed, because
612
+ // container section is optional.
613
+ if (section_id != expected_section_id &&
614
+ (expected_section_id != DATA_SECTION || section_id != CONTAINER_SECTION))
615
+ return get_section_missing_error (expected_section_id);
616
+
617
+ switch (section_id)
618
+ {
619
+ case TERMINATOR:
620
+ state = State::terminated;
621
+ break ;
622
+ case TYPE_SECTION:
623
+ expected_section_id = CODE_SECTION;
624
+ state = State::section_size;
625
+ break ;
626
+ case CODE_SECTION:
627
+ {
628
+ if (it >= container_end - 1 )
629
+ return EOFValidationError::incomplete_section_number;
630
+ section_num = read_uint16_be (it);
631
+ it += 2 ;
632
+ if (section_num == 0 )
633
+ return EOFValidationError::zero_section_size;
634
+ if (section_num > CODE_SECTION_NUMBER_LIMIT)
635
+ return EOFValidationError::too_many_code_sections;
636
+ expected_section_id = DATA_SECTION;
637
+ state = State::section_size;
638
+ break ;
639
+ }
640
+ case DATA_SECTION:
641
+ expected_section_id = TERMINATOR;
642
+ state = State::section_size;
643
+ break ;
644
+ case CONTAINER_SECTION:
645
+ {
646
+ if (it >= container_end - 1 )
647
+ return EOFValidationError::incomplete_section_number;
648
+ section_num = read_uint16_be (it);
649
+ it += 2 ;
650
+ if (section_num == 0 )
651
+ return EOFValidationError::zero_section_size;
652
+ if (section_num > CONTAINER_SECTION_NUMBER_LIMIT)
653
+ return EOFValidationError::too_many_container_sections;
654
+ expected_section_id = DATA_SECTION;
655
+ state = State::section_size;
656
+ break ;
657
+ }
658
+ default :
659
+ assert (false );
660
+ }
661
+ break ;
662
+ }
663
+ case State::section_size:
664
+ {
665
+ if (section_id == CODE_SECTION || section_id == CONTAINER_SECTION)
666
+ {
667
+ assert (section_num > 0 ); // Guaranteed by previous validation step.
668
+ for (size_t i = 0 ; i < section_num; ++i)
669
+ {
670
+ if (it >= container_end - 1 )
671
+ return EOFValidationError::incomplete_section_size;
672
+ const auto section_size = read_uint16_be (it);
673
+ it += 2 ;
674
+ if (section_size == 0 )
675
+ return EOFValidationError::zero_section_size;
676
+
677
+ section_headers[section_id].emplace_back (section_size);
678
+ }
679
+ }
680
+ else // TYPES_SECTION or DATA_SECTION
681
+ {
682
+ if (it >= container_end - 1 )
683
+ return EOFValidationError::incomplete_section_size;
684
+ const auto section_size = read_uint16_be (it);
685
+ it += 2 ;
686
+ if (section_size == 0 && section_id != DATA_SECTION)
687
+ return EOFValidationError::zero_section_size;
688
+
689
+ section_headers[section_id].emplace_back (section_size);
690
+ }
691
+
692
+ state = State::section_id;
693
+ break ;
694
+ }
695
+ case State::terminated:
696
+ return EOFValidationError::impossible;
697
+ }
698
+ }
699
+
700
+ if (state != State::terminated)
701
+ return EOFValidationError::section_headers_not_terminated;
702
+
703
+ const auto section_bodies_without_data =
704
+ section_headers[TYPE_SECTION].front () +
705
+ std::accumulate (
706
+ section_headers[CODE_SECTION].begin (), section_headers[CODE_SECTION].end (), 0 ) +
707
+ std::accumulate (section_headers[CONTAINER_SECTION].begin (),
708
+ section_headers[CONTAINER_SECTION].end (), 0 );
709
+ const auto remaining_container_size = container_end - it;
710
+ // Only data section may be truncated, so remaining_container size must be at least
711
+ // declared_size_without_data
712
+ if (remaining_container_size < section_bodies_without_data)
713
+ return EOFValidationError::invalid_section_bodies_size;
714
+
715
+ if (section_headers[TYPE_SECTION][0 ] != section_headers[CODE_SECTION].size () * 4 )
716
+ return EOFValidationError::invalid_type_section_size;
717
+
718
+ return section_headers;
719
+ }
720
+
731
721
// / This function expects the prefix and version to be valid, as it ignores it.
732
722
EOF1Header read_valid_eof1_header (bytes_view container)
733
723
{
@@ -905,8 +895,6 @@ std::string_view get_error_message(EOFValidationError err) noexcept
905
895
return " invalid_container_section_index" ;
906
896
case EOFValidationError::eofcreate_with_truncated_container:
907
897
return " eofcreate_with_truncated_container" ;
908
- case EOFValidationError::stray_bytes_subcontainer:
909
- return " stray_bytes_subcontainer" ;
910
898
case EOFValidationError::impossible:
911
899
return " impossible" ;
912
900
}
0 commit comments