summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2021-33196.patch
blob: 2e2dc62c4961c23a6e4f9cdddf21a0ce4399d8bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
From 74242baa4136c7a9132a8ccd9881354442788c8c Mon Sep 17 00:00:00 2001
From: Roland Shoemaker <roland@golang.org>
Date: Tue, 11 May 2021 11:31:31 -0700
Subject: [PATCH] archive/zip: only preallocate File slice if reasonably sized

Since the number of files in the EOCD record isn't validated, it isn't
safe to preallocate Reader.Files using that field. A malformed archive
can indicate it contains up to 1 << 128 - 1 files. We can still safely
preallocate the slice by checking if the specified number of files in
the archive is reasonable, given the size of the archive.

Thanks to the OSS-Fuzz project for discovering this issue and to
Emmanuel Odeke for reporting it.

Fixes #46242
Fixes CVE-2021-33196

Change-Id: I3c76d8eec178468b380d87fdb4a3f2cb06f0ee76
Reviewed-on: https://go-review.googlesource.com/c/go/+/318909
Trust: Roland Shoemaker <roland@golang.org>
Trust: Katie Hockman <katie@golang.org>
Trust: Joe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>

Upstream-Status: Backport
CVE: CVE-2021-33196
Signed-off-by: Armin Kuster <akuster@mvista.com>

---
 src/archive/zip/reader.go      | 10 +++++-
 src/archive/zip/reader_test.go | 59 ++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)

Index: go/src/archive/zip/reader.go
===================================================================
--- go.orig/src/archive/zip/reader.go
+++ go/src/archive/zip/reader.go
@@ -84,7 +84,15 @@ func (z *Reader) init(r io.ReaderAt, siz
 		return err
 	}
 	z.r = r
-	z.File = make([]*File, 0, end.directoryRecords)
+	// Since the number of directory records is not validated, it is not
+	// safe to preallocate z.File without first checking that the specified
+	// number of files is reasonable, since a malformed archive may
+	// indicate it contains up to 1 << 128 - 1 files. Since each file has a
+	// header which will be _at least_ 30 bytes we can safely preallocate
+	// if (data size / 30) >= end.directoryRecords.
+	if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
+		z.File = make([]*File, 0, end.directoryRecords)
+	}
 	z.Comment = end.comment
 	rs := io.NewSectionReader(r, 0, size)
 	if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
Index: go/src/archive/zip/reader_test.go
===================================================================
--- go.orig/src/archive/zip/reader_test.go
+++ go/src/archive/zip/reader_test.go
@@ -1070,3 +1070,62 @@ func TestIssue12449(t *testing.T) {
 		t.Errorf("Error reading the archive: %v", err)
 	}
 }
+
+func TestCVE202133196(t *testing.T) {
+	// Archive that indicates it has 1 << 128 -1 files,
+	// this would previously cause a panic due to attempting
+	// to allocate a slice with 1 << 128 -1 elements.
+	data := []byte{
+		0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
+		0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
+		0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
+		0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
+		0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
+		0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
+		0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
+		0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
+		0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
+		0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
+		0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0x00, 0x00,
+	}
+	_, err := NewReader(bytes.NewReader(data), int64(len(data)))
+	if err != ErrFormat {
+		t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
+	}
+
+	// Also check that an archive containing a handful of empty
+	// files doesn't cause an issue
+	b := bytes.NewBuffer(nil)
+	w := NewWriter(b)
+	for i := 0; i < 5; i++ {
+		_, err := w.Create("")
+		if err != nil {
+			t.Fatalf("Writer.Create failed: %s", err)
+		}
+	}
+	if err := w.Close(); err != nil {
+		t.Fatalf("Writer.Close failed: %s", err)
+	}
+	r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
+	if err != nil {
+		t.Fatalf("NewReader failed: %s", err)
+	}
+	if len(r.File) != 5 {
+		t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
+	}
+}