verify.py: Don't try to verify bytecode against compiled code if

magics of running interpreter mismatch bytecode to be compared.
load_module() now returns the magic found in the code object file.
This commit is contained in:
rocky
2015-12-18 22:04:50 -05:00
parent 6bc425b45e
commit 0a49c7a15b
4 changed files with 42 additions and 29 deletions

View File

@@ -77,13 +77,18 @@ def _load_file(filename):
return co return co
def load_module(filename): def load_module(filename):
''' """
load a module without importing it load a module without importing it.
load_module(filename: string): code_object load_module(filename: string): version, magic_int, code_object
filename: name of file containing Python byte-code object filename: name of file containing Python byte-code object
(normally a .pyc) (normally a .pyc)
code_object: code_object from this file code_object: code_object from this file
''' version: Python major/minor value e.g. 2.7. or 3.4
magic_int: more specific than version. The actual byte code version of the
code object
"""
with open(filename, 'rb') as fp: with open(filename, 'rb') as fp:
magic = fp.read(4) magic = fp.read(4)
@@ -117,11 +122,11 @@ def load_module(filename):
co = uncompyle6.marsh.load_code(fp, magic_int) co = uncompyle6.marsh.load_code(fp, magic_int)
pass pass
return version, co return version, magic_int, co
def uncompyle(version, co, out=None, showasm=False, showast=False): def uncompyle(version, co, out=None, showasm=False, showast=False):
""" """
diassembles and deparses a given code block 'co' disassembles and deparses a given code block 'co'
""" """
assert isinstance(co, types.CodeType) assert isinstance(co, types.CodeType)
@@ -173,7 +178,7 @@ def uncompyle_file(filename, outstream=None, showasm=False, showast=False):
decompile Python byte-code file (.pyc) decompile Python byte-code file (.pyc)
""" """
check_object_path(filename) check_object_path(filename)
version, co = load_module(filename) version, magic_int, co = load_module(filename)
if type(co) == list: if type(co) == list:
for con in co: for con in co:
uncompyle(version, con, outstream, showasm, showast) uncompyle(version, con, outstream, showasm, showast)
@@ -282,9 +287,13 @@ def main(in_base, out_base, files, codes, outfile=None,
outstream.close() outstream.close()
if do_verify: if do_verify:
try: try:
verify.compare_code_with_srcfile(infile, outfile) msg = verify.compare_code_with_srcfile(infile, outfile)
if not outfile: print('\n# okay decompyling', infile, __memUsage()) if not outfile:
if not msg:
print('\n# okay decompyling %s' % infile)
okay_files += 1 okay_files += 1
else:
print('\n# %s\n\t%s', infile, msg)
except verify.VerifyCmpError as e: except verify.VerifyCmpError as e:
verify_failed_files += 1 verify_failed_files += 1
os.rename(outfile, outfile + '_unverified') os.rename(outfile, outfile + '_unverified')

View File

@@ -1,8 +1,6 @@
from __future__ import print_function from __future__ import print_function
import struct, sys import imp, struct, sys
__all__ = ['magics', 'versions', 'magic2int']
def __build_magic(magic): def __build_magic(magic):
if (sys.version_info >= (3, 0)): if (sys.version_info >= (3, 0)):
@@ -13,6 +11,8 @@ def __build_magic(magic):
def magic2int(magic): def magic2int(magic):
return struct.unpack('Hcc', magic)[0] return struct.unpack('Hcc', magic)[0]
PYTHON_MAGIC_INT = magic2int(imp.get_magic())
by_magic = {} by_magic = {}
by_version = {} by_version = {}
@@ -96,15 +96,13 @@ def __show(text, magic):
print(text, struct.unpack('BBBB', magic), struct.unpack('HBB', magic)) print(text, struct.unpack('BBBB', magic), struct.unpack('HBB', magic))
def test(): def test():
import imp
magic_20 = magics['2.0'] magic_20 = magics['2.0']
current = imp.get_magic() current = imp.get_magic()
current_version = struct.unpack('HBB', current)[0]
magic_current = by_magic[ current ] magic_current = by_magic[ current ]
print(type(magic_20), len(magic_20), repr(magic_20)) print(type(magic_20), len(magic_20), repr(magic_20))
print() print()
print('This Python interpreter has version', magic_current) print('This Python interpreter has version', magic_current)
print('Magic code: ', current_version) print('Magic code: ', PYTHON_MAGIC_INT)
print(type(magic_20), len(magic_20), repr(magic_20)) print(type(magic_20), len(magic_20), repr(magic_20))
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -15,14 +15,13 @@ to produce a code object
from __future__ import print_function from __future__ import print_function
import imp, sys, types import sys, types
from struct import unpack from struct import unpack
from uncompyle6.magics import magic2int from uncompyle6.magics import PYTHON_MAGIC_INT
internStrings = [] internStrings = []
PYTHON_MAGIC_INT = magic2int(imp.get_magic())
PYTHON3 = (sys.version_info >= (3, 0)) PYTHON3 = (sys.version_info >= (3, 0))
if PYTHON3: if PYTHON3:

View File

@@ -1,18 +1,22 @@
# #
# (C) Copyright 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com> # (C) Copyright 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# (C) Copyright 2015 by Rocky Bernstein
# #
# byte-code verifier for uncompyle """
# byte-code verification
"""
from __future__ import print_function from __future__ import print_function
import dis, inspect, operator, sys, types import dis, inspect, operator, types
import uncompyle6 import uncompyle6
import uncompyle6.scanner as scanner import uncompyle6.scanner as scanner
from uncompyle6 import PYTHON3
from uncompyle6.magics import PYTHON_MAGIC_INT
# FIXME: DRY # FIXME: DRY
if (sys.version_info >= (3, 0)): if PYTHON3:
truediv = operator.truediv truediv = operator.truediv
from functools import reduce from functools import reduce
else: else:
@@ -344,14 +348,19 @@ class Token(scanner.Token):
def compare_code_with_srcfile(pyc_filename, src_filename): def compare_code_with_srcfile(pyc_filename, src_filename):
"""Compare a .pyc with a source code file.""" """Compare a .pyc with a source code file."""
version, code_obj1 = uncompyle6.load_module(pyc_filename) version, magic_int, code_obj1 = uncompyle6.load_module(pyc_filename)
if magic_int != PYTHON_MAGIC_INT:
msg = ("Can't compare code - Python is running with magic %s, but code is magic %s "
% (PYTHON_MAGIC_INT, magic_int))
return msg
code_obj2 = uncompyle6._load_file(src_filename) code_obj2 = uncompyle6._load_file(src_filename)
cmp_code_objects(version, code_obj1, code_obj2) cmp_code_objects(version, code_obj1, code_obj2)
return None
def compare_files(pyc_filename1, pyc_filename2): def compare_files(pyc_filename1, pyc_filename2):
"""Compare two .pyc files.""" """Compare two .pyc files."""
version, code_obj1 = uncompyle6.load_module(pyc_filename1) version, magic_int1, code_obj1 = uncompyle6.load_module(pyc_filename1)
version, code_obj2 = uncompyle6.load_module(pyc_filename2) version, magic_int2, code_obj2 = uncompyle6.load_module(pyc_filename2)
cmp_code_objects(version, code_obj1, code_obj2) cmp_code_objects(version, code_obj1, code_obj2)
if __name__ == '__main__': if __name__ == '__main__':
@@ -359,6 +368,4 @@ if __name__ == '__main__':
t2 = Token('LOAD_CONST', -421, 'code_object _expandLang', 55) t2 = Token('LOAD_CONST', -421, 'code_object _expandLang', 55)
print(repr(t1)) print(repr(t1))
print(repr(t2)) print(repr(t2))
print(t1.type == t2.type, t1.attr == t2.attr)
if (sys.version_info < (3, 0)):
print(cmp(t1, t2), cmp(t1.type, t2.type), cmp(t1.attr, t2.attr))