New submission from Matt Bogosian: It looks like there's a problem examining ``.tar`` files with no entries:
``` $ # ================================================================== $ # Extract test cases (attached to this bug report) $ tar xpvf tarfail.tar.bz2 x tarfail/ x tarfail/tarfail.py x tarfail/test.tar x tarfail/test.tar.bz2 $ cd tarfail $ # ================================================================== $ # Note that test.tar.bz2 is just test.tar, but bzip2'ed: $ bzip2 -c test.tar | openssl dgst -sha256 ; openssl dgst -sha256 test.tar.bz2 f4fad25a0e7a451ed906b76846efd6d2699a65b40795b29553addc35bf9a75c8 SHA256(test.tar.bz2)= f4fad25a0e7a451ed906b76846efd6d2699a65b40795b29553addc35bf9a75c8 $ wc -c test.tar* # these are not empty files 10240 test.tar 46 test.tar.bz2 10286 total $ tar tpvf test.tar # no entries $ tar tpvf test.tar.bz2 # no entries $ # ================================================================== $ # test.tar.bz2 works, but test.tar causes problems (tested in 2.7, $ # 3.5, and 3.6): $ python2.7 tarfail.py opening /…/tarfail/test.tar.bz2 opening /…/tarfail/test.tar E ====================================================================== ERROR: test_next (__main__.TestTarFileNext) ---------------------------------------------------------------------- Traceback (most recent call last): File "tarfail.py", line 29, in test_next next_info = tar_file.next() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py", line 2350, in next self.fileobj.seek(self.offset - 1) IOError: [Errno 22] Invalid argument ---------------------------------------------------------------------- Ran 1 test in 0.005s FAILED (errors=1) $ python3.5 tarfail.py opening /…/tarfail/test.tar.bz2 opening /…/tarfail/test.tar E ====================================================================== ERROR: test_next (__main__.TestTarFileNext) ---------------------------------------------------------------------- Traceback (most recent call last): File "tarfail.py", line 29, in test_next next_info = tar_file.next() File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tarfile.py", line 2273, in next self.fileobj.seek(self.offset - 1) OSError: [Errno 22] Invalid argument ---------------------------------------------------------------------- Ran 1 test in 0.066s FAILED (errors=1) $ python3.6 tarfail.py opening /…/tarfail/test.tar.bz2 opening /…/tarfail/test.tar E ====================================================================== ERROR: test_next (__main__.TestTarFileNext) ---------------------------------------------------------------------- Traceback (most recent call last): File "tarfail.py", line 29, in test_next next_info = tar_file.next() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tarfile.py", line 2279, in next self.fileobj.seek(self.offset - 1) OSError: [Errno 22] Invalid argument ---------------------------------------------------------------------- Ran 1 test in 0.090s FAILED (errors=1) ``` Here's the issue (as far as I can tell): ``` $ ipdb tarfail.py > /…/tarfail/tarfail.py(3)<module>() 2 ----> 3 from __future__ import ( 4 absolute_import, division, print_function, unicode_literals, ipdb> b /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py:2350 Breakpoint 1 at /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py:2350 ipdb> c opening /…/tarfail/test.tar.bz2 > /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py(2350)next() 2349 if self.offset != self.fileobj.tell(): 1> 2350 self.fileobj.seek(self.offset - 1) 2351 if not self.fileobj.read(1): ipdb> self.fileobj <bz2.BZ2File object at 0x1067791d0> ipdb> self.offset, self.fileobj.tell(), self.offset - 1 (0, 512, -1) ipdb> c opening /…/tarfail/test.tar > /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py(2350)next() 2349 if self.offset != self.fileobj.tell(): 1> 2350 self.fileobj.seek(self.offset - 1) 2351 if not self.fileobj.read(1): ipdb> self.fileobj <open file u'/…/tarfail/test.tar', mode 'rb' at 0x10676dae0> ipdb> self.offset, self.fileobj.tell(), self.offset - 1 (0, 512, -1) ipdb> c E ====================================================================== ERROR: test_next (__main__.TestTarFileNext) ---------------------------------------------------------------------- Traceback (most recent call last): File "tarfail.py", line 29, in test_next next_info = tar_file.next() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/tarfile.py", line 2350, in next self.fileobj.seek(self.offset - 1) IOError: [Errno 22] Invalid argument ---------------------------------------------------------------------- Ran 1 test in 38.300s FAILED (errors=1) The program exited via sys.exit(). Exit status: True > /…/tarfail/tarfail.py(3)<module>() 2 ----> 3 from __future__ import ( 4 absolute_import, division, print_function, unicode_literals, ipdb> EOF ``` Apparently, ``bz2.BZ2File`` allows seeking to pre-0 (negative) values, whereas more primitive files are not so forgiving. The offending line looks like it can be traced back to this commit: https://github.com/python/cpython/blame/2.7/Lib/tarfile.py#L2350 https://github.com/python/cpython/blame/3.3/Lib/tarfile.py#L2252 https://github.com/python/cpython/blame/3.4/Lib/tarfile.py#L2252 https://github.com/python/cpython/blame/3.5/Lib/tarfile.py#L2273 https://github.com/python/cpython/blame/3.6/Lib/tarfile.py#L2286 (My apologies for not catching this sooner.) ---------- components: Library (Lib) files: tarfail.tar.bz2 messages: 289253 nosy: posita priority: normal severity: normal status: open title: tarfile chokes on reading .tar file with no entries (but does fine if the same file is bzip2'ed) type: crash versions: Python 2.7, Python 3.3, Python 3.4, Python 3.5, Python 3.6, Python 3.7 Added file: http://bugs.python.org/file46712/tarfail.tar.bz2 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue29760> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com