Skip to content

archive/tar: base-256 UID/GID values silently truncate on 32-bit platforms #82121

Closed

Description

@prasanna8585

Go version

Reproduced with go1.24.7 (GOARCH=386). The same code is unchanged on master (dfe2e7b).

Output of go env in your module/workspace:

Linux, GOARCH=386 (the bug only shows on platforms where int is 32 bits).

What did you do?

Read a tar header whose uid (or gid) field uses the GNU base-256 encoding with a value outside the 32-bit int range, for example uid = 4294967296 (2^32).

In readHeader (src/archive/tar/reader.go), the V7 uid/gid fields are parsed with parseNumeric, which returns an int64, and then converted with int(...) without a range check:

hdr.Uid = int(p.parseNumeric(v7.uid()))
hdr.Gid = int(p.parseNumeric(v7.gid()))

The same truncation was fixed for PAX uid/gid records in CL 822060 (#81129), but the base-256 path in readHeader was not covered.

Minimal reproduction, as a test in package tar (run with GOARCH=386 go test -run TestReadHeaderBase256IDOverflow archive/tar):

var blk block
var f formatter
v7 := blk.toV7()
copy(v7.name(), "file")
v7.typeFlag()[0] = TypeReg
f.formatOctal(v7.mode(), 0644)
f.formatNumeric(v7.uid(), 1<<32) // encoded as base-256
f.formatOctal(v7.size(), 0)
f.formatOctal(v7.modTime(), 0)
blk.setFormat(FormatGNU)
hdr, err := NewReader(bytes.NewReader(append(blk[:], make([]byte, 2*blockSize)...))).Next()

What did you see happen?

On GOARCH=386, Next() returns no error and hdr.Uid == 0. The encoded owner (4294967296) is silently replaced by 0 (root). Values such as 2^31 wrap to negative.

What did you expect to see?

Next() should return ErrHeader, consistent with the PAX uid/gid handling after CL 822060.

Notes

This was first reported privately to security@golang.org; the security team classified it as a regular bug and suggested filing it here. I have a fix with a test ready to send as a CL.

Activity

  1. houtinghang commented on Oct 10, 2026

    @houtinghang
    Contributor

    This looks like a duplicate of #81446, which reports the same missing range check on the V7/USTAR path in readHeader (the PAX path was fixed in CL 822060 for #81129).

    A fix is already pending review: https://go.dev/cl/831024 (GitHub PR #81471). It adds the same math.MaxInt/math.MinInt check that mergePAX uses, so an out-of-range base-256 uid/gid returns ErrHeader instead of being truncated.

    I applied CL 831024 on top of current master (966c78e) and ran it with GOARCH=386: base-256 uid values of 2^31, 2^32 and -2^31-1 all now return ErrHeader, and go test archive/tar passes on both 386 and amd64.

    So it may be better to review/+1 that CL rather than send a second one. Perhaps this issue can be closed as a duplicate of #81446.

  2. prasanna8585 commented on Oct 10, 2026

    @prasanna8585
    Author

    Thanks for checking, @houtinghang. I agree this is a duplicate of #81446 (I hadn’t found it when filing). For what it’s worth, I independently reproduced the same truncation on GOARCH=386 (base-256 uid/gid of 2^31, 2^32 and -2^40 all accepted without error) and verified the same math.MaxInt/math.MinInt check fixes it, with go test archive/tar passing on 386 and amd64. I’ll +1 CL 831024 instead of sending a second change. Closing as a duplicate of #81446.

  3. added a commit that references this issue on Oct 10, 2026
    1c40f24
  4. gopherbot commented on Oct 10, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/831024 mentions this issue: archive/tar: return ErrHeader on V7/USTAR UID/GID integer overflow

  5. added 2 commits that reference this issue on Oct 14, 2026
    a4ede38
    a4d44d5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions