Fixed assertionrewrite._read_pyc to handle corrupted pyc files properly

This seems to be the cause for issues #437 and #301.

--HG--
branch : assertionrewrite-currupted-pyc
This commit is contained in:
Bruno Oliveira 2014-08-02 18:01:28 -03:00
parent 97b671057d
commit fd4485a540
2 changed files with 26 additions and 1 deletions

View File

@ -308,7 +308,10 @@ def _read_pyc(source, pyc):
if (len(data) != 8 or data[:4] != imp.get_magic() or
struct.unpack("<l", data[4:])[0] != mtime):
return None
co = marshal.load(fp)
try:
co = marshal.load(fp)
except (EOFError, ValueError, TypeError): # see docs
return None
if not isinstance(co, types.CodeType):
# That's interesting....
return None

View File

@ -539,3 +539,25 @@ class TestAssertionRewriteHookDetails(object):
result.stdout.fnmatch_lines([
'* 1 passed*',
])
def test_read_pyc(self, tmpdir):
"""
Ensure that the `_read_pyc` can properly deal with corrupted pyc files.
In those circumstances it should just give up instead of generating
an exception that is propagated to the caller.
"""
import py_compile
from _pytest.assertion.rewrite import _read_pyc
source = tmpdir.join('source.py')
pyc = source + 'c'
source.write('def test(): pass')
py_compile.compile(str(source), str(pyc))
contents = pyc.read(mode='rb')
strip_bytes = 20 # header is around 8 bytes, strip a little more
assert len(contents) > strip_bytes
pyc.write(contents[:strip_bytes], mode='wb')
assert _read_pyc(source, str(pyc)) is None # no error