Skip to content

Commit 0a078f2

Browse files
committed
archive/tar: fix the archive/tar.Writer CVE
The remainder of: golang/go@0bf7ee9 Reference from #76 (comment) Signed-off-by: Vincent Batts <[email protected]>
1 parent b8ca13f commit 0a078f2

File tree

4 files changed

+40
-1
lines changed

4 files changed

+40
-1
lines changed

archive/tar/reader_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package tar
66

77
import (
88
"bytes"
9+
"compress/bzip2"
910
"crypto/md5"
1011
"errors"
1112
"fmt"
@@ -243,6 +244,9 @@ func TestReader(t *testing.T) {
243244
}, {
244245
file: "testdata/pax-bad-hdr-file.tar",
245246
err: ErrHeader,
247+
}, {
248+
file: "testdata/pax-bad-hdr-large.tar.bz2",
249+
err: ErrFieldTooLong,
246250
}, {
247251
file: "testdata/pax-bad-mtime-file.tar",
248252
err: ErrHeader,
@@ -625,9 +629,14 @@ func TestReader(t *testing.T) {
625629
}
626630
defer f.Close()
627631

632+
var fr io.Reader = f
633+
if strings.HasSuffix(v.file, ".bz2") {
634+
fr = bzip2.NewReader(fr)
635+
}
636+
628637
// Capture all headers and checksums.
629638
var (
630-
tr = NewReader(f)
639+
tr = NewReader(fr)
631640
hdrs []*Header
632641
chksums []string
633642
rdbuf = make([]byte, 8)
156 Bytes
Binary file not shown.

archive/tar/writer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
199199
flag = TypeXHeader
200200
}
201201
data := buf.String()
202+
if len(data) > maxSpecialFileSize {
203+
return ErrFieldTooLong
204+
}
202205
if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal {
203206
return err // Global headers return here
204207
}

archive/tar/writer_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,33 @@ func TestIssue12594(t *testing.T) {
10061006
}
10071007
}
10081008

1009+
func TestWriteLongHeader(t *testing.T) {
1010+
for _, test := range []struct {
1011+
name string
1012+
h *Header
1013+
}{{
1014+
name: "name too long",
1015+
h: &Header{Name: strings.Repeat("a", maxSpecialFileSize)},
1016+
}, {
1017+
name: "linkname too long",
1018+
h: &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)},
1019+
}, {
1020+
name: "uname too long",
1021+
h: &Header{Uname: strings.Repeat("a", maxSpecialFileSize)},
1022+
}, {
1023+
name: "gname too long",
1024+
h: &Header{Gname: strings.Repeat("a", maxSpecialFileSize)},
1025+
}, {
1026+
name: "PAX header too long",
1027+
h: &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}},
1028+
}} {
1029+
w := NewWriter(io.Discard)
1030+
if err := w.WriteHeader(test.h); err != ErrFieldTooLong {
1031+
t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err)
1032+
}
1033+
}
1034+
}
1035+
10091036
// testNonEmptyWriter wraps an io.Writer and ensures that
10101037
// Write is never called with an empty buffer.
10111038
type testNonEmptyWriter struct{ io.Writer }

0 commit comments

Comments
 (0)