@@ -255,7 +255,8 @@ struct InstructionValidationResult
255
255
};
256
256
257
257
std::variant<InstructionValidationResult, EOFValidationError> validate_instructions (
258
- evmc_revision rev, const EOF1Header& header, size_t code_idx, bytes_view container) noexcept
258
+ evmc_revision rev, const EOF1Header& header, ContainerKind kind, size_t code_idx,
259
+ bytes_view container) noexcept
259
260
{
260
261
const bytes_view code{header.get_code (container, code_idx)};
261
262
assert (!code.empty ()); // guaranteed by EOF headers validation
@@ -323,9 +324,20 @@ std::variant<InstructionValidationResult, EOFValidationError> validate_instructi
323
324
if (container_idx >= header.container_sizes .size ())
324
325
return EOFValidationError::invalid_container_section_index;
325
326
327
+ if (op == OP_RETURNCONTRACT)
328
+ {
329
+ if (kind == ContainerKind::runtime || kind == ContainerKind::initcode_runtime)
330
+ return EOFValidationError::incompatible_container_kind;
331
+ }
332
+
326
333
subcontainer_references.emplace_back (container_idx, Opcode{op});
327
334
++i;
328
335
}
336
+ else if (op == OP_RETURN || op == OP_STOP)
337
+ {
338
+ if (kind == ContainerKind::initcode || kind == ContainerKind::initcode_runtime)
339
+ return EOFValidationError::incompatible_container_kind;
340
+ }
329
341
else
330
342
i += instr::traits[op].immediate_size ;
331
343
}
@@ -572,20 +584,22 @@ std::variant<EOFValidationError, int32_t> validate_max_stack_height(
572
584
return max_stack_height_it->max ;
573
585
}
574
586
575
- EOFValidationError validate_eof1 (evmc_revision rev, bytes_view main_container) noexcept
587
+ EOFValidationError validate_eof1 (
588
+ evmc_revision rev, ContainerKind main_container_kind, bytes_view main_container) noexcept
576
589
{
577
590
struct ContainerValidation
578
591
{
579
592
bytes_view bytes;
580
- bool referenced_by_eofcreate = false ;
593
+ ContainerKind kind ;
581
594
};
582
595
// Queue of containers left to process
583
596
std::queue<ContainerValidation> container_queue;
584
- container_queue.push ({main_container, false });
597
+
598
+ container_queue.push ({main_container, main_container_kind});
585
599
586
600
while (!container_queue.empty ())
587
601
{
588
- const auto & [container, referenced_by_eofcreate ] = container_queue.front ();
602
+ const auto & [container, container_kind ] = container_queue.front ();
589
603
590
604
// Validate header
591
605
auto error_or_header = validate_header (rev, container);
@@ -603,6 +617,7 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
603
617
604
618
const auto subcontainer_count = header.container_sizes .size ();
605
619
std::vector<bool > subcontainer_referenced_by_eofcreate (subcontainer_count, false );
620
+ std::vector<bool > subcontainer_referenced_by_returncontract (subcontainer_count, false );
606
621
607
622
while (!code_sections_queue.empty ())
608
623
{
@@ -616,7 +631,7 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
616
631
617
632
// Validate instructions
618
633
const auto instr_validation_result_or_error =
619
- validate_instructions (rev, header, code_idx, container);
634
+ validate_instructions (rev, header, container_kind, code_idx, container);
620
635
if (const auto * error =
621
636
std::get_if<EOFValidationError>(&instr_validation_result_or_error))
622
637
return *error;
@@ -629,6 +644,10 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
629
644
{
630
645
if (opcode == OP_EOFCREATE)
631
646
subcontainer_referenced_by_eofcreate[index ] = true ;
647
+ else if (opcode == OP_RETURNCONTRACT)
648
+ subcontainer_referenced_by_returncontract[index ] = true ;
649
+ else
650
+ intx::unreachable ();
632
651
}
633
652
634
653
// TODO(C++23): can use push_range()
@@ -657,7 +676,8 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
657
676
{
658
677
if (main_container == container)
659
678
return EOFValidationError::toplevel_container_truncated;
660
- if (referenced_by_eofcreate)
679
+ if (container_kind == ContainerKind::initcode ||
680
+ container_kind == ContainerKind::initcode_runtime)
661
681
return EOFValidationError::eofcreate_with_truncated_container;
662
682
}
663
683
@@ -666,7 +686,18 @@ EOFValidationError validate_eof1(evmc_revision rev, bytes_view main_container) n
666
686
{
667
687
const bytes_view subcontainer{header.get_container (container, subcont_idx)};
668
688
669
- container_queue.push ({subcontainer, subcontainer_referenced_by_eofcreate[subcont_idx]});
689
+ const bool eofcreate = subcontainer_referenced_by_eofcreate[subcont_idx];
690
+ const bool returncontract = subcontainer_referenced_by_returncontract[subcont_idx];
691
+
692
+ // TODO Validate whether subcontainer was referenced by any instruction
693
+
694
+ auto subcontainer_kind = ContainerKind::initcode_runtime;
695
+ if (!eofcreate)
696
+ subcontainer_kind = ContainerKind::runtime;
697
+ else if (!returncontract)
698
+ subcontainer_kind = ContainerKind::initcode;
699
+
700
+ container_queue.push ({subcontainer, subcontainer_kind});
670
701
}
671
702
672
703
container_queue.pop ();
@@ -852,9 +883,10 @@ uint8_t get_eof_version(bytes_view container) noexcept
852
883
0 ;
853
884
}
854
885
855
- EOFValidationError validate_eof (evmc_revision rev, bytes_view container) noexcept
886
+ EOFValidationError validate_eof (
887
+ evmc_revision rev, ContainerKind kind, bytes_view container) noexcept
856
888
{
857
- return validate_eof1 (rev, container);
889
+ return validate_eof1 (rev, kind, container);
858
890
}
859
891
860
892
std::string_view get_error_message (EOFValidationError err) noexcept
@@ -935,6 +967,10 @@ std::string_view get_error_message(EOFValidationError err) noexcept
935
967
return " eofcreate_with_truncated_container" ;
936
968
case EOFValidationError::toplevel_container_truncated:
937
969
return " toplevel_container_truncated" ;
970
+ case EOFValidationError::ambiguous_container_kind:
971
+ return " ambiguous_container_kind" ;
972
+ case EOFValidationError::incompatible_container_kind:
973
+ return " incompatible_container_kind" ;
938
974
case EOFValidationError::impossible:
939
975
return " impossible" ;
940
976
}
0 commit comments