Skip to content

Commit 69c6093

Browse files
committed
xz: fix a security issue for readUvarint
readUvarint could be provided a sequence of bytes where the application would never stop. That is the same issue that has been recently reported for the Go Standard Library as CVE-2020-16845. The fix simply adds a check for the number of bytes read and reports an overflow after more than 10 bytes are read, which is $\ceil{\frac{64}{7}}$. The commit also includes a test to ensure that the error is returned. I thank Github user 0xdecaf for reporting the issue.
1 parent 067145b commit 69c6093

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

bits.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ var errOverflowU64 = errors.New("xz: uvarint overflows 64-bit unsigned integer")
5454

5555
// readUvarint reads a uvarint from the given byte reader.
5656
func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
57+
const maxUvarintLen = 10
58+
5759
var s uint
5860
i := 0
5961
for {
@@ -62,8 +64,11 @@ func readUvarint(r io.ByteReader) (x uint64, n int, err error) {
6264
return x, i, err
6365
}
6466
i++
67+
if i > maxUvarintLen {
68+
return x, i, errOverflowU64
69+
}
6570
if b < 0x80 {
66-
if i > 10 || i == 10 && b > 1 {
71+
if i == maxUvarintLen && b > 1 {
6772
return x, i, errOverflowU64
6873
}
6974
return x | uint64(b)<<s, i, nil

bits_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,14 @@ func TestUvarint(t *testing.T) {
3131
}
3232
}
3333
}
34+
35+
func TestUvarIntCVE_2020_16845(t *testing.T) {
36+
var a = []byte{0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
37+
0x88, 0x89, 0x8a, 0x8b}
38+
39+
r := bytes.NewReader(a)
40+
_, _, err := readUvarint(r)
41+
if err != errOverflowU64 {
42+
t.Fatalf("readUvarint overflow not detected")
43+
}
44+
}

0 commit comments

Comments
 (0)