@@ -8,12 +8,25 @@ import (
8
8
)
9
9
10
10
var (
11
- ErrOverflow = errors .New ("varints larger than uint64 not yet supported" )
11
+ ErrOverflow = errors .New ("varints larger than uint63 not supported" )
12
12
ErrUnderflow = errors .New ("varints malformed, could not reach the end" )
13
13
ErrNotMinimal = errors .New ("varint not minimally encoded" )
14
14
)
15
15
16
+ const (
17
+ // MaxLenUvarint63 is the maximum number of bytes representing an uvarint in
18
+ // this encoding, supporting a maximum value of 2^63 (uint63), aka
19
+ // MaxValueUvarint63.
20
+ MaxLenUvarint63 = 9
21
+
22
+ // MaxValueUvarint63 is the maximum encodable uint63 value.
23
+ MaxValueUvarint63 = (1 << 63 ) - 1
24
+ )
25
+
16
26
// UvarintSize returns the size (in bytes) of `num` encoded as a unsigned varint.
27
+ //
28
+ // This may return a size greater than MaxUvarintLen63, which would be an
29
+ // illegal value, and would be rejected by readers.
17
30
func UvarintSize (num uint64 ) int {
18
31
bits := bits .Len64 (num )
19
32
q , r := bits / 7 , bits % 7
@@ -39,10 +52,14 @@ func FromUvarint(buf []byte) (uint64, int, error) {
39
52
var x uint64
40
53
var s uint
41
54
for i , b := range buf {
55
+ if (i == 8 && b >= 0x80 ) || i >= MaxLenUvarint63 {
56
+ // this is the 9th and last byte we're willing to read, but it
57
+ // signals there's more (1 in MSB).
58
+ // or this is the >= 10th byte, and for some reason we're still here.
59
+ return 0 , 0 , ErrOverflow
60
+ }
42
61
if b < 0x80 {
43
- if i > 9 || i == 9 && b > 1 {
44
- return 0 , 0 , ErrOverflow
45
- } else if b == 0 && s > 0 {
62
+ if b == 0 && s > 0 {
46
63
return 0 , 0 , ErrNotMinimal
47
64
}
48
65
return x | uint64 (b )<< s , i + 1 , nil
@@ -70,12 +87,14 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
70
87
}
71
88
return 0 , err
72
89
}
90
+ if (i == 8 && b >= 0x80 ) || i >= MaxLenUvarint63 {
91
+ // this is the 9th and last byte we're willing to read, but it
92
+ // signals there's more (1 in MSB).
93
+ // or this is the >= 10th byte, and for some reason we're still here.
94
+ return 0 , ErrOverflow
95
+ }
73
96
if b < 0x80 {
74
- if i > 9 || i == 9 && b > 1 {
75
- return 0 , ErrOverflow
76
- } else if b == 0 && s > 0 {
77
- // we should never _finish_ on a 0 byte if we
78
- // have more than one byte.
97
+ if b == 0 && s > 0 {
79
98
return 0 , ErrNotMinimal
80
99
}
81
100
return x | uint64 (b )<< s , nil
@@ -89,6 +108,9 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
89
108
//
90
109
// This is provided for convenience so users of this library can avoid built-in
91
110
// varint functions and easily audit code for uses of those functions.
111
+ //
112
+ // Make sure that x is smaller or equal to MaxValueUvarint63, otherwise this
113
+ // function will produce values that may be rejected by readers.
92
114
func PutUvarint (buf []byte , x uint64 ) int {
93
115
return binary .PutUvarint (buf , x )
94
116
}
0 commit comments