@@ -518,7 +518,7 @@ func decodeDecoder(s *Stream, val reflect.Value) error {
518
518
}
519
519
520
520
// Kind represents the kind of value contained in an RLP stream.
521
- type Kind int
521
+ type Kind int8
522
522
523
523
const (
524
524
Byte Kind = iota
@@ -561,22 +561,16 @@ type ByteReader interface {
561
561
type Stream struct {
562
562
r ByteReader
563
563
564
- // number of bytes remaining to be read from r.
565
- remaining uint64
566
- limited bool
567
-
568
- // auxiliary buffer for integer decoding
569
- uintbuf []byte
570
-
571
- kind Kind // kind of value ahead
572
- size uint64 // size of value ahead
573
- byteval byte // value of single byte in type tag
574
- kinderr error // error from last readKind
575
- stack []listpos
564
+ remaining uint64 // number of bytes remaining to be read from r
565
+ size uint64 // size of value ahead
566
+ kinderr error // error from last readKind
567
+ stack []uint64 // list sizes
568
+ uintbuf [8 ]byte // auxiliary buffer for integer decoding
569
+ kind Kind // kind of value ahead
570
+ byteval byte // value of single byte in type tag
571
+ limited bool // true if input limit is in effect
576
572
}
577
573
578
- type listpos struct { pos , size uint64 }
579
-
580
574
// NewStream creates a new decoding stream reading from r.
581
575
//
582
576
// If r implements the ByteReader interface, Stream will
@@ -646,8 +640,8 @@ func (s *Stream) Raw() ([]byte, error) {
646
640
s .kind = - 1 // rearm Kind
647
641
return []byte {s .byteval }, nil
648
642
}
649
- // the original header has already been read and is no longer
650
- // available. read content and put a new header in front of it.
643
+ // The original header has already been read and is no longer
644
+ // available. Read content and put a new header in front of it.
651
645
start := headsize (size )
652
646
buf := make ([]byte , uint64 (start )+ size )
653
647
if err := s .readFull (buf [start :]); err != nil {
@@ -730,7 +724,14 @@ func (s *Stream) List() (size uint64, err error) {
730
724
if kind != List {
731
725
return 0 , ErrExpectedList
732
726
}
733
- s .stack = append (s .stack , listpos {0 , size })
727
+
728
+ // Remove size of inner list from outer list before pushing the new size
729
+ // onto the stack. This ensures that the remaining outer list size will
730
+ // be correct after the matching call to ListEnd.
731
+ if inList , limit := s .listLimit (); inList {
732
+ s .stack [len (s .stack )- 1 ] = limit - size
733
+ }
734
+ s .stack = append (s .stack , size )
734
735
s .kind = - 1
735
736
s .size = 0
736
737
return size , nil
@@ -739,17 +740,13 @@ func (s *Stream) List() (size uint64, err error) {
739
740
// ListEnd returns to the enclosing list.
740
741
// The input reader must be positioned at the end of a list.
741
742
func (s * Stream ) ListEnd () error {
742
- if len (s .stack ) == 0 {
743
+ // Ensure that no more data is remaining in the current list.
744
+ if inList , listLimit := s .listLimit (); ! inList {
743
745
return errNotInList
744
- }
745
- tos := s .stack [len (s .stack )- 1 ]
746
- if tos .pos != tos .size {
746
+ } else if listLimit > 0 {
747
747
return errNotAtEOL
748
748
}
749
749
s .stack = s .stack [:len (s .stack )- 1 ] // pop
750
- if len (s .stack ) > 0 {
751
- s .stack [len (s .stack )- 1 ].pos += tos .size
752
- }
753
750
s .kind = - 1
754
751
s .size = 0
755
752
return nil
@@ -777,7 +774,7 @@ func (s *Stream) Decode(val interface{}) error {
777
774
778
775
err = decoder (s , rval .Elem ())
779
776
if decErr , ok := err .(* decodeError ); ok && len (decErr .ctx ) > 0 {
780
- // add decode target type to error so context has more meaning
777
+ // Add decode target type to error so context has more meaning.
781
778
decErr .ctx = append (decErr .ctx , fmt .Sprint ("(" , rtyp .Elem (), ")" ))
782
779
}
783
780
return err
@@ -800,6 +797,9 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) {
800
797
case * bytes.Reader :
801
798
s .remaining = uint64 (br .Len ())
802
799
s .limited = true
800
+ case * bytes.Buffer :
801
+ s .remaining = uint64 (br .Len ())
802
+ s .limited = true
803
803
case * strings.Reader :
804
804
s .remaining = uint64 (br .Len ())
805
805
s .limited = true
@@ -818,10 +818,8 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) {
818
818
s .size = 0
819
819
s .kind = - 1
820
820
s .kinderr = nil
821
- if s .uintbuf == nil {
822
- s .uintbuf = make ([]byte , 8 )
823
- }
824
821
s .byteval = 0
822
+ s .uintbuf = [8 ]byte {}
825
823
}
826
824
827
825
// Kind returns the kind and size of the next value in the
@@ -836,35 +834,29 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) {
836
834
// the value. Subsequent calls to Kind (until the value is decoded)
837
835
// will not advance the input reader and return cached information.
838
836
func (s * Stream ) Kind () (kind Kind , size uint64 , err error ) {
839
- var tos * listpos
840
- if len (s .stack ) > 0 {
841
- tos = & s .stack [len (s .stack )- 1 ]
842
- }
843
- if s .kind < 0 {
844
- s .kinderr = nil
845
- // Don't read further if we're at the end of the
846
- // innermost list.
847
- if tos != nil && tos .pos == tos .size {
848
- return 0 , 0 , EOL
849
- }
850
- s .kind , s .size , s .kinderr = s .readKind ()
851
- if s .kinderr == nil {
852
- if tos == nil {
853
- // At toplevel, check that the value is smaller
854
- // than the remaining input length.
855
- if s .limited && s .size > s .remaining {
856
- s .kinderr = ErrValueTooLarge
857
- }
858
- } else {
859
- // Inside a list, check that the value doesn't overflow the list.
860
- if s .size > tos .size - tos .pos {
861
- s .kinderr = ErrElemTooLarge
862
- }
863
- }
837
+ if s .kind >= 0 {
838
+ return s .kind , s .size , s .kinderr
839
+ }
840
+
841
+ // Check for end of list. This needs to be done here because readKind
842
+ // checks against the list size, and would return the wrong error.
843
+ inList , listLimit := s .listLimit ()
844
+ if inList && listLimit == 0 {
845
+ return 0 , 0 , EOL
846
+ }
847
+ // Read the actual size tag.
848
+ s .kind , s .size , s .kinderr = s .readKind ()
849
+ if s .kinderr == nil {
850
+ // Check the data size of the value ahead against input limits. This
851
+ // is done here because many decoders require allocating an input
852
+ // buffer matching the value size. Checking it here protects those
853
+ // decoders from inputs declaring very large value size.
854
+ if inList && s .size > listLimit {
855
+ s .kinderr = ErrElemTooLarge
856
+ } else if s .limited && s .size > s .remaining {
857
+ s .kinderr = ErrValueTooLarge
864
858
}
865
859
}
866
- // Note: this might return a sticky error generated
867
- // by an earlier call to readKind.
868
860
return s .kind , s .size , s .kinderr
869
861
}
870
862
@@ -891,37 +883,35 @@ func (s *Stream) readKind() (kind Kind, size uint64, err error) {
891
883
s .byteval = b
892
884
return Byte , 0 , nil
893
885
case b < 0xB8 :
894
- // Otherwise, if a string is 0-55 bytes long,
895
- // the RLP encoding consists of a single byte with value 0x80 plus the
896
- // length of the string followed by the string. The range of the first
897
- // byte is thus [0x80, 0xB7].
886
+ // Otherwise, if a string is 0-55 bytes long, the RLP encoding consists
887
+ // of a single byte with value 0x80 plus the length of the string
888
+ // followed by the string. The range of the first byte is thus [0x80, 0xB7].
898
889
return String , uint64 (b - 0x80 ), nil
899
890
case b < 0xC0 :
900
- // If a string is more than 55 bytes long, the
901
- // RLP encoding consists of a single byte with value 0xB7 plus the length
902
- // of the length of the string in binary form, followed by the length of
903
- // the string, followed by the string. For example, a length-1024 string
904
- // would be encoded as 0xB90400 followed by the string. The range of
905
- // the first byte is thus [0xB8, 0xBF].
891
+ // If a string is more than 55 bytes long, the RLP encoding consists of a
892
+ // single byte with value 0xB7 plus the length of the length of the
893
+ // string in binary form, followed by the length of the string, followed
894
+ // by the string. For example, a length-1024 string would be encoded as
895
+ // 0xB90400 followed by the string. The range of the first byte is thus
896
+ // [0xB8, 0xBF].
906
897
size , err = s .readUint (b - 0xB7 )
907
898
if err == nil && size < 56 {
908
899
err = ErrCanonSize
909
900
}
910
901
return String , size , err
911
902
case b < 0xF8 :
912
- // If the total payload of a list
913
- // (i.e. the combined length of all its items) is 0-55 bytes long, the
914
- // RLP encoding consists of a single byte with value 0xC0 plus the length
915
- // of the list followed by the concatenation of the RLP encodings of the
916
- // items. The range of the first byte is thus [0xC0, 0xF7].
903
+ // If the total payload of a list (i.e. the combined length of all its
904
+ // items) is 0-55 bytes long, the RLP encoding consists of a single byte
905
+ // with value 0xC0 plus the length of the list followed by the
906
+ // concatenation of the RLP encodings of the items. The range of the
907
+ // first byte is thus [0xC0, 0xF7].
917
908
return List , uint64 (b - 0xC0 ), nil
918
909
default :
919
- // If the total payload of a list is more than 55 bytes long,
920
- // the RLP encoding consists of a single byte with value 0xF7
921
- // plus the length of the length of the payload in binary
922
- // form, followed by the length of the payload, followed by
923
- // the concatenation of the RLP encodings of the items. The
924
- // range of the first byte is thus [0xF8, 0xFF].
910
+ // If the total payload of a list is more than 55 bytes long, the RLP
911
+ // encoding consists of a single byte with value 0xF7 plus the length of
912
+ // the length of the payload in binary form, followed by the length of
913
+ // the payload, followed by the concatenation of the RLP encodings of
914
+ // the items. The range of the first byte is thus [0xF8, 0xFF].
925
915
size , err = s .readUint (b - 0xF7 )
926
916
if err == nil && size < 56 {
927
917
err = ErrCanonSize
@@ -940,22 +930,20 @@ func (s *Stream) readUint(size byte) (uint64, error) {
940
930
return uint64 (b ), err
941
931
default :
942
932
start := int (8 - size )
943
- for i := 0 ; i < start ; i ++ {
944
- s .uintbuf [i ] = 0
945
- }
933
+ s .uintbuf = [8 ]byte {}
946
934
if err := s .readFull (s .uintbuf [start :]); err != nil {
947
935
return 0 , err
948
936
}
949
937
if s .uintbuf [start ] == 0 {
950
- // Note: readUint is also used to decode integer
951
- // values. The error needs to be adjusted to become
952
- // ErrCanonInt in this case.
938
+ // Note: readUint is also used to decode integer values.
939
+ // The error needs to be adjusted to become ErrCanonInt in this case.
953
940
return 0 , ErrCanonSize
954
941
}
955
- return binary .BigEndian .Uint64 (s .uintbuf ), nil
942
+ return binary .BigEndian .Uint64 (s .uintbuf [:] ), nil
956
943
}
957
944
}
958
945
946
+ // readFull reads into buf from the underlying stream.
959
947
func (s * Stream ) readFull (buf []byte ) (err error ) {
960
948
if err := s .willRead (uint64 (len (buf ))); err != nil {
961
949
return err
@@ -977,6 +965,7 @@ func (s *Stream) readFull(buf []byte) (err error) {
977
965
return err
978
966
}
979
967
968
+ // readByte reads a single byte from the underlying stream.
980
969
func (s * Stream ) readByte () (byte , error ) {
981
970
if err := s .willRead (1 ); err != nil {
982
971
return 0 , err
@@ -988,16 +977,16 @@ func (s *Stream) readByte() (byte, error) {
988
977
return b , err
989
978
}
990
979
980
+ // willRead is called before any read from the underlying stream. It checks
981
+ // n against size limits, and updates the limits if n doesn't overflow them.
991
982
func (s * Stream ) willRead (n uint64 ) error {
992
983
s .kind = - 1 // rearm Kind
993
984
994
- if len (s .stack ) > 0 {
995
- // check list overflow
996
- tos := s .stack [len (s .stack )- 1 ]
997
- if n > tos .size - tos .pos {
985
+ if inList , limit := s .listLimit (); inList {
986
+ if n > limit {
998
987
return ErrElemTooLarge
999
988
}
1000
- s .stack [len (s .stack )- 1 ]. pos += n
989
+ s .stack [len (s .stack )- 1 ] = limit - n
1001
990
}
1002
991
if s .limited {
1003
992
if n > s .remaining {
@@ -1007,3 +996,11 @@ func (s *Stream) willRead(n uint64) error {
1007
996
}
1008
997
return nil
1009
998
}
999
+
1000
+ // listLimit returns the amount of data remaining in the innermost list.
1001
+ func (s * Stream ) listLimit () (inList bool , limit uint64 ) {
1002
+ if len (s .stack ) == 0 {
1003
+ return false , 0
1004
+ }
1005
+ return true , s .stack [len (s .stack )- 1 ]
1006
+ }
0 commit comments