Skip to content

tarfile writes a member's old pax records after its name or other attributes are changed #161045

Description

@gpshead

Bug report

Bug description:

A TarInfo read from an archive keeps the member's pax records in pax_headers, and TarInfo.create_pax_header() gives an existing record priority over the attribute. If a program changes name (or linkname, uname, gname, uid, gid, mtime, size) on such a member, by assignment or with TarInfo.replace(), and adds it to a new archive in the default pax format, the new value goes into the ustar header but the old record is written in front of it and wins for every pax reader. Any member with a long or non-ASCII name has a path record, so no unusual input is needed.

import io, tarfile

src = io.BytesIO()
with tarfile.open(fileobj=src, mode="w") as tar:
    tar.addfile(tarfile.TarInfo("d\xe9j\xe0-vu.txt"))       # non-ASCII: gets a pax "path" record
    tar.addfile(tarfile.TarInfo("plain.txt"))

src.seek(0)
dst = io.BytesIO()
with tarfile.open(fileobj=src) as tar, tarfile.open(fileobj=dst, mode="w") as out:
    for member in tar:
        member.name = "prefix/" + member.name.encode("ascii", "replace").decode()
        out.addfile(member)

dst.seek(0)
with tarfile.open(fileobj=dst) as tar:
    print(tar.getnames())

This prints ['déjà-vu.txt', 'prefix/plain.txt']; expected ['prefix/d?j?-vu.txt', 'prefix/plain.txt']. member.replace(name=...) behaves the same, and a GNU.sparse.name record has the same effect as path. USTAR_FORMAT and GNU_FORMAT output is not affected.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. self-assigned this
    on Oct 31, 2026
  2. added
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    on Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions