Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/archive/tar/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ import (
"time"
)

// BUG: Use of the Uid and Gid fields in Header could overflow on 32-bit
// architectures. If a large value is encountered when decoding, the result
// stored in Header will be the truncated version.
// BUG: Use of the Uid and Gid fields in Header cannot represent values above
// int on 32-bit architectures when writing.

var tarinsecurepath = godebug.New("tarinsecurepath")

Expand Down
4 changes: 2 additions & 2 deletions src/archive/tar/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
hdr.Linkname = p.parseString(v7.linkName())
hdr.Size = p.parseNumeric(v7.size())
hdr.Mode = p.parseNumeric(v7.mode())
hdr.Uid = int(p.parseNumeric(v7.uid()))
hdr.Gid = int(p.parseNumeric(v7.gid()))
hdr.Uid = p.parseInt(v7.uid())
hdr.Gid = p.parseInt(v7.gid())
hdr.ModTime = time.Unix(p.parseNumeric(v7.modTime()), 0)

// Unpack format specific fields.
Expand Down
67 changes: 67 additions & 0 deletions src/archive/tar/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1749,3 +1749,70 @@ func TestMergePAXIntegerOverflow(t *testing.T) {
}
}

func TestHeaderNumericIDIntegerOverflow(t *testing.T) {
makeHeader := func(uid, gid int64) []byte {
var blk block
var f formatter
v7 := blk.toV7()
copy(v7.name(), "testfile")
v7.typeFlag()[0] = TypeReg
f.formatOctal(v7.mode(), 0644)
f.formatNumeric(v7.uid(), uid)
f.formatNumeric(v7.gid(), gid)
f.formatOctal(v7.size(), 0)
f.formatOctal(v7.modTime(), 0)
blk.setFormat(FormatGNU)
return blk[:]
}

vectors := []struct {
name string
uid int64
gid int64
wantErr bool
}{
{"Normal", 1000, 1000, false},
{"BoundaryMaxInt32", 1<<31 - 1, 1000, false},
{"OverflowUID_1<<31", 1 << 31, 1000, math.MaxInt < 1<<31},
{"OverflowGID_1<<31", 1000, 1 << 31, math.MaxInt < 1<<31},
{"OverflowUID_1<<32", 1 << 32, 1000, math.MaxInt < 1<<32},
{"OverflowGID_1<<32", 1000, 1 << 32, math.MaxInt < 1<<32},
{"BoundaryMinInt32", -1 << 31, 1000, false},
{"UnderflowUID_-1<<31-1", -1<<31 - 1, 1000, math.MinInt > -1<<31-1},
{"UnderflowGID_-1<<31-1", 1000, -1<<31 - 1, math.MinInt > -1<<31-1},
{"UnderflowUID_-1<<40", -1 << 40, 1000, math.MinInt > -1<<40},
}

for _, tt := range vectors {
t.Run(tt.name, func(t *testing.T) {
raw := makeHeader(tt.uid, tt.gid)
var buf bytes.Buffer
buf.Write(raw)
buf.Write(make([]byte, 1024))

tr := NewReader(&buf)
hdr, err := tr.Next()
if tt.wantErr {
if err == nil {
t.Fatal("Expected non-nil error")
}
if !errors.Is(err, ErrHeader) {
t.Fatalf("Expected error of type ErrHeader, got %v", err)
}
if hdr != nil {
t.Fatalf("Expected nil header on error, got %+v", hdr)
}
} else {
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if hdr.Uid != int(tt.uid) {
t.Fatalf("hdr.Uid = %d, want %d", hdr.Uid, tt.uid)
}
if hdr.Gid != int(tt.gid) {
t.Fatalf("hdr.Gid = %d, want %d", hdr.Gid, tt.gid)
}
}
})
}
}
12 changes: 12 additions & 0 deletions src/archive/tar/strconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package tar
import (
"bytes"
"fmt"
"math"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -134,6 +135,17 @@ func (p *parser) parseNumeric(b []byte) int64 {
return p.parseOctal(b)
}

// parseInt is like parseNumeric but reports ErrHeader if the value does not
// fit in the platform's int.
func (p *parser) parseInt(b []byte) int {
n := p.parseNumeric(b)
if n > math.MaxInt || n < math.MinInt {
p.err = ErrHeader
return 0
}
return int(n)
}

// formatNumeric encodes x into b using base-8 (octal) encoding if possible.
// Otherwise it will attempt to use base-256 (binary) encoding.
func (f *formatter) formatNumeric(b []byte, x int64) {
Expand Down
Loading