python / python/cpython

tarfile silently stops/skips on bad member header (e.g. checksum mismatch)

Aperta
#120,740 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:

When reading a tar archive that includes a file with a bad header (such as a checksum mismatch), getmembers simply stops listing the members at that file, without reporting an error, and ignoring the files that come after it (Edit: unless ignore_zeros=True is set).

I would expect instead that getmembers lists all members, and extractfile raises a TarError when trying to extract a file with an invalid header (such as a bad chksum or typeflag).

import os
import contextlib
import subprocess
from io import BytesIO
from tarfile import TarFile, TarInfo
from tempfile import TemporaryDirectory

# generate a tar file in memory
bio = BytesIO()
with TarFile(mode="w", fileobj=bio, errorlevel=2) as tf:
    ti = TarInfo()
    ti.size = 3
    for name, data in (("foo", b"123"), ("bar", b"456"), ("quz", b"789")):
        ti.name = name
        tf.addfile(ti, BytesIO(data))

# break the checksum of the second file 'bar'
assert b"\x00006425\x00" in bio.getvalue()
broken = bio.getvalue().replace(b"\x00006425\x00", b"\x00106425\x00")

# try to read the tar file
with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
    for ti in tf.getmembers():
        print(repr(ti.name))
        with tf.extractfile(ti) as fh:
            print(repr(fh.read()))
# => only "foo" is extracted

with TemporaryDirectory() as td:
    with contextlib.chdir(td):
        with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
            tf.extractall()
        print(os.listdir())
        # => again only "foo" is extracted
        os.unlink("foo")
        with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
            tf.extractall(filter="data")
        print(os.listdir())
        # => filter doesn't change anything
        with open("test.tar", "wb") as fh:
            fh.write(broken)
        subprocess.run(["tar", "tvf", "test.tar"], check=False)
        # => GNU tar 1.34 correctly identifies error and continues processing

Output:

'foo'
b'123'
['foo']
['foo']
-rw-r--r-- 0/0               3 1970-01-01 00:00 foo
tar: Skipping to next header
-rw-r--r-- 0/0               3 1970-01-01 00:00 quz
tar: Exiting with failure status due to previous errors
CPython versions tested on:

3.12, 3.13

Operating systems tested on:

Linux, Windows

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Riproduci il comportamento con l'esempio BytesIO fornito, quindi parti da TarFile.getmembers(), extractfile() ed extractall(), i punti di ingresso indicati nel report. Traccia come viene gestita un'intestazione di membro non valida e come vengono raggiunte le intestazioni successive. Il lavoro è completato quando l'intestazione errata viene segnalata come richiesto, mentre i membri validi successivi rimangono elaborabili, e il comportamento interessato è coperto da test.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
48/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.