@@ -734,6 +734,26 @@ pub struct Instructions<'a> {
734
734
}
735
735
736
736
impl < ' a > Instructions < ' a > {
737
+ /// Set the iterator to end so that it won't iterate any longer
738
+ fn kill ( & mut self ) {
739
+ let len = self . data . len ( ) ;
740
+ self . data . nth ( len. max ( 1 ) - 1 ) ;
741
+ }
742
+
743
+ /// takes `len` bytes long slice from iterator and returns it advancing iterator
744
+ /// if the iterator is not long enough `None` is returned and the iterator is killed
745
+ /// to avoid returning an infinite stream of errors.
746
+ fn take_slice_or_kill ( & mut self , len : usize ) -> Option < & ' a [ u8 ] > {
747
+ if self . data . len ( ) >= len {
748
+ let slice = & self . data . as_slice ( ) [ ..len] ;
749
+ self . data . nth ( len. max ( 1 ) - 1 ) ;
750
+ Some ( slice)
751
+ } else {
752
+ self . kill ( ) ;
753
+ None
754
+ }
755
+ }
756
+
737
757
fn next_push_data_len ( & mut self , len : usize , max : usize ) -> Option < Result < Instruction < ' a > , Error > > {
738
758
let n = match read_uint_iter ( & mut self . data , len) {
739
759
Ok ( n) => n,
@@ -742,19 +762,15 @@ impl<'a> Instructions<'a> {
742
762
// Overflow actually means early end of script (script is definitely shorter
743
763
// than `usize::max_value()`)
744
764
Err ( UintError :: EarlyEndOfScript ) | Err ( UintError :: NumericOverflow ) => {
745
- let data_len = self . data . len ( ) ;
746
- self . data . nth ( data_len) ; // Kill iterator so that it does not return an infinite stream of errors
765
+ self . kill ( ) ;
747
766
return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
748
767
} ,
749
768
} ;
750
769
if self . enforce_minimal && n < max {
751
- let data_len = self . data . len ( ) ;
752
- self . data . nth ( data_len) ; // Kill iterator so that it does not return an infinite stream of errors
770
+ self . kill ( ) ;
753
771
return Some ( Err ( Error :: NonMinimalPush ) ) ;
754
772
}
755
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data . as_slice ( ) [ ..n] ) ) ) ;
756
- self . data . nth ( n. max ( 1 ) - 1 ) ;
757
- ret
773
+ Some ( self . take_slice_or_kill ( n) . map ( Instruction :: PushBytes ) . ok_or ( Error :: EarlyEndOfScript ) )
758
774
}
759
775
}
760
776
@@ -773,22 +789,21 @@ impl<'a> Iterator for Instructions<'a> {
773
789
// casting is safe because we don't support 16-bit architectures
774
790
let n = n as usize ;
775
791
776
- if self . data . len ( ) < n {
777
- let data_len = self . data . len ( ) ;
778
- self . data . nth ( data_len) ; // Kill iterator so that it does not return an infinite stream of errors
779
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
780
- }
781
- if self . enforce_minimal {
782
- // index acceess is safe because we checked the lenght above
783
- if n == 1 && ( self . data . as_slice ( ) [ 0 ] == 0x81 || ( self . data . as_slice ( ) [ 0 ] > 0 && self . data . as_slice ( ) [ 0 ] <= 16 ) ) {
784
- let data_len = self . data . len ( ) ;
785
- self . data . nth ( data_len) ; // Kill iterator so that it does not return an infinite stream of errors
786
- return Some ( Err ( Error :: NonMinimalPush ) ) ;
792
+ let op_byte = self . data . as_slice ( ) . first ( ) ;
793
+ match ( self . enforce_minimal , op_byte, n) {
794
+ ( true , Some ( & op_byte) , 1 ) if op_byte == 0x81 || ( op_byte > 0 && op_byte <= 16 ) => {
795
+ self . kill ( ) ;
796
+ Some ( Err ( Error :: NonMinimalPush ) )
797
+ } ,
798
+ ( _, None , 0 ) => {
799
+ // the iterator is already empty, may as well use this information to avoid
800
+ // whole take_slice_or_kill function
801
+ Some ( Ok ( Instruction :: PushBytes ( & [ ] ) ) )
802
+ } ,
803
+ _ => {
804
+ Some ( self . take_slice_or_kill ( n) . map ( Instruction :: PushBytes ) . ok_or ( Error :: EarlyEndOfScript ) )
787
805
}
788
806
}
789
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data . as_slice ( ) [ ..n] ) ) ) ;
790
- self . data . nth ( n. max ( 1 ) - 1 ) ;
791
- ret
792
807
}
793
808
opcodes:: Class :: Ordinary ( opcodes:: Ordinary :: OP_PUSHDATA1 ) => {
794
809
self . next_push_data_len ( 1 , 76 )
0 commit comments