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

Reply via email to