Skip to content

Commit

Permalink
archive/tar: fix for CVE-2022-2879
Browse files Browse the repository at this point in the history
Fixes: #76

In a specially crafted tar archive can cause `io.ReadAll()` to overrun
the memory.
The fix is taken from upstream golang, as this tar-split repo carries an
old fork from upstream.

Thanks to @tojoos and @bainsy88 for reporting.

References:
- https://nvd.nist.gov/vuln/detail/cve-2022-2879
- golang/go@0bf7ee9
- https://go-review.googlesource.com/c/go/+/439355/2/src/archive/tar/reader.go#106

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
  • Loading branch information
vbatts committed Jan 20, 2025
1 parent cc780ee commit 1c425c4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
4 changes: 4 additions & 0 deletions archive/tar/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ const (
blockSize = 512 // Size of each block in a tar stream
nameSize = 100 // Max length of the name field in USTAR format
prefixSize = 155 // Max length of the prefix field in USTAR format

// Max length of a special file (PAX header, GNU long name or link).
// This matches the limit used by libarchive.
maxSpecialFileSize = 1 << 20
)

// blockPadding computes the number of bytes needed to pad offset up to the
Expand Down
14 changes: 12 additions & 2 deletions archive/tar/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (tr *Reader) next() (*Header, error) {
continue // This is a meta header affecting the next header
case TypeGNULongName, TypeGNULongLink:
format.mayOnlyBe(FormatGNU)
realname, err := io.ReadAll(tr)
realname, err := readSpecialFile(tr)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -338,7 +338,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
// parsePAX parses PAX headers.
// If an extended header (type 'x') is invalid, ErrHeader is returned
func parsePAX(r io.Reader) (map[string]string, error) {
buf, err := io.ReadAll(r)
buf, err := readSpecialFile(r)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -889,6 +889,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) {
return n, err
}

// readSpecialFile is like io.ReadAll except it returns
// ErrFieldTooLong if more than maxSpecialFileSize is read.
func readSpecialFile(r io.Reader) ([]byte, error) {
buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1))
if len(buf) > maxSpecialFileSize {
return nil, ErrFieldTooLong
}
return buf, err
}

// discard skips n bytes in r, reporting an error if unable to do so.
func discard(tr *Reader, n int64) error {
var seekSkipped, copySkipped int64
Expand Down

0 comments on commit 1c425c4

Please # to comment.