@@ -734,6 +734,26 @@ pub struct Instructions<'a> {
734734}
735735
736736impl < ' 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+
737757 fn next_push_data_len ( & mut self , len : usize , max : usize ) -> Option < Result < Instruction < ' a > , Error > > {
738758 let n = match read_uint_iter ( & mut self . data , len) {
739759 Ok ( n) => n,
@@ -742,19 +762,15 @@ impl<'a> Instructions<'a> {
742762 // Overflow actually means early end of script (script is definitely shorter
743763 // than `usize::max_value()`)
744764 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 ( ) ;
747766 return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
748767 } ,
749768 } ;
750769 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 ( ) ;
753771 return Some ( Err ( Error :: NonMinimalPush ) ) ;
754772 }
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 ) )
758774 }
759775}
760776
@@ -773,22 +789,21 @@ impl<'a> Iterator for Instructions<'a> {
773789 // casting is safe because we don't support 16-bit architectures
774790 let n = n as usize ;
775791
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 ) )
787805 }
788806 }
789- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data . as_slice ( ) [ ..n] ) ) ) ;
790- self . data . nth ( n. max ( 1 ) - 1 ) ;
791- ret
792807 }
793808 opcodes:: Class :: Ordinary ( opcodes:: Ordinary :: OP_PUSHDATA1 ) => {
794809 self . next_push_data_len ( 1 , 76 )
0 commit comments