Skip to content

Allow zero-length members in tar files - #10014

Merged
radarhere merged 1 commit into
python-pillow:mainfrom
hugovk:fix-tario
Sep 18, 2026
Merged

radarhere merged 1 commit into
python-pillow:mainfrom
hugovk:fix-tario

Conversation

@hugovk

@hugovk hugovk commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes regression from #10012.

@radarhere

Copy link
Copy Markdown
Member

I would have thought a check that we weren't seeking backwards was the most direct?

What specification did you use to conclude that zero-length members need to be supported?

@hugovk

hugovk commented Sep 17, 2026

Copy link
Copy Markdown
Member Author

I would have thought a check that we weren't seeking backwards was the most direct?

This creates a tar file with a block with a negative offset:

import os
import sys
import tempfile

from PIL import TarIO


def header(name, size):
    block = bytearray(512)
    block[: len(name)] = name.encode()
    block[124:135] = str(size).encode().rjust(11)
    return block


path = os.path.join(tempfile.mkdtemp(), "t.tar")
with open(path, "wb") as f:
    f.write(header("a", -1))
    f.write(header("b", 0))

try:
    TarIO.TarIO(path, "b")
except ValueError as e:
    print("rejected:", e)
else:
    print("accepted but should reject")
    sys.exit(1)

With the PR we get "rejected: size must not be negative".

With this instead:

             offset = (size + 511) & ~511
-            if offset <= 0:
-                msg = "offset must be positive"
+            if offset < 0:
+                self.fh.close()
+                msg = "cannot seek backwards"
                 raise ValueError(msg)
             self.fh.seek(offset, io.SEEK_CUR)

We get "accepted but should reject".


What specification did you use to conclude that zero-length members need to be supported?

It's needed for hard links and symlinks defined in POSIX.1-2024, which are zero length:

The size field is the size of the file in octets. If the typeflag field is set to specify a file to be of type 1 (a hard link) or 2 (a symbolic link), the size field shall be specified as zero.

https://pubs.opengroup.org/onlinepubs/9799919799/utilities/pax.html

@radarhere
radarhere merged commit 4c1ed27 into python-pillow:main Sep 18, 2026
79 of 83 checks passed
@hugovk
hugovk deleted the fix-tario branch September 18, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants