python / python/cpython

tarfile: don't interpret GNU-style atime as ustar-style path prefix

Đang mở
#155,629 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

stdlib type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

Bug report

Bug description:

The GNU and ustar tar format families have slightly overlapping header definitions: ustar says that bytes 345:500 are used for the "path prefix" i.e. for paths longer than the 100 char limit in the path field, while old-style GNU ("oldgnu") says that 345:356 are used for storing an atime attribute for the member.

Consequently, the two overlap (partially), and a tar parser should check the header's magic to determine how to interpret that byte range.

At the moment, CPython does not use the header's magic, and instead unconditionally interprets that range as a ustar-style prefix:

https://github.com/python/cpython/blob/b11e749f7590e9a0907db908fa3e7e76c772c28f/Lib/tarfile.py#L1354

and then unconditionally uses that prefix as long as the member type (not the header type) isn't a special GNU member type:

https://github.com/python/cpython/blob/b11e749f7590e9a0907db908fa3e7e76c772c28f/Lib/tarfile.py#L1383-L1385

The end result of this is that tarfile can extract a file with a surprising name, whereas other parsers extract with the correct (non-ustar-prefixed) name.

MRE:

import io
import tarfile

member = tarfile.TarInfo("victim")
header = bytearray(member.tobuf(format=tarfile.GNU_FORMAT))

# Old-GNU atime field: valid octal timestamp 1.
header[345:357] = b"00000000001\0"

# Recalculate checksum.
header[148:156] = b" " * 8
header[148:156] = f"{sum(header):06o}\0 ".encode("ascii")

archive = bytes(header) + b"\0" * 1024

with tarfile.open(fileobj=io.BytesIO(archive), mode="r:") as tf:
    print(tf.getnames())

On a main build as of b11e749f7590e9a0907db908fa3e7e76c772c28f, this produces:

['00000000001/victim']

whereas the output should be ['victim'], since the format is GNU_FORMAT instead of a ustar-family format.

I think the fix for this is to tweak the obj.name assignment to only use prefix when the magic bytes match POSIX_MAGIC, i.e. not GNU_MAGIC or any legacy (v7, pre-ustar) magic.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs
  • gh-155706

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu trong Lib/tarfile.py, tại phần phân tích tiền tố và phép gán obj.name quanh các dòng được tham chiếu, sau đó tái hiện vấn đề bằng MRE được cung cấp. Hoàn tất khi kho lưu trữ GNU-format trả về ['victim'] thay vì ['00000000001/victim']; hãy kiểm tra PR được liên kết gh-155706 trước khi bắt đầu.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
tooling
Loại issue
Lỗi
Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.