Add Python 1.3 decompilation ..

Reduced checking via "make check-short"
This commit is contained in:
rocky
2018-06-13 12:26:21 -04:00
parent 3ac4f1ee61
commit b7942bc5f2
13 changed files with 116 additions and 11 deletions

View File

@@ -11,8 +11,9 @@ Introduction
------------ ------------
*uncompyle6* translates Python bytecode back into equivalent Python *uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 1.4, and 2.1 to source code. It accepts bytecodes from Python version 1.3 to version
3.7 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode. 3.7, spanning over 22 years of Python releases. We include Dropbox's
Python 2.5 bytecode and some PyPy bytecode.
Why this? Why this?
--------- ---------

View File

@@ -22,7 +22,7 @@ COVER_DIR=../tmp/grammar-cover
# Run short tests # Run short tests
check-short: check-short:
@$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \ @$(PYTHON) -V && PYTHON_VERSION=`$(PYTHON) -V 2>&1 | cut -d ' ' -f 2 | cut -d'.' -f1,2`; \
$(MAKE) check-bytecode $(MAKE) check-bytecode-short
# Run all tests # Run all tests
check: check:
@@ -91,16 +91,31 @@ check-bytecode-3:
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \ --bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 --bytecode-pypy3.2 --bytecode-3.4 --bytecode-3.5 --bytecode-3.6 --bytecode-pypy3.2
#: Check deparsing bytecode that works running Python 2 and Python 3 #: Check deparsing on selected bytecode 3.x
check-bytecode-3-short:
$(PYTHON) test_pythonlib.py \
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6
#: Check deparsing bytecode on all Python 2 and Python 3 versions
check-bytecode: check-bytecode-3 check-bytecode: check-bytecode-3
$(PYTHON) test_pythonlib.py \ $(PYTHON) test_pythonlib.py \
--bytecode-1.4 --bytecode-1.5 \ --bytecode-1.3 --bytecode-1.4 --bytecode-1.5 \
--bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \ --bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
--bytecode-2.1 --bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \ --bytecode-2.1 --bytecode-2.2 --bytecode-2.3 --bytecode-2.4 \
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \ --bytecode-2.5 --bytecode-2.6 --bytecode-2.7 \
--bytecode-pypy2.7 --bytecode-pypy2.7
#: Check deparsing bytecode on selected Python 2 and Python 3 versions
check-bytecode-short: check-bytecode-3-short
$(PYTHON) test_pythonlib.py \
--bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
#: Check deparsing bytecode 1.3 only
check-bytecode-1.3:
$(PYTHON) test_pythonlib.py --bytecode-1.3
#: Check deparsing bytecode 1.4 only #: Check deparsing bytecode 1.4 only
check-bytecode-1.4: check-bytecode-1.4:
$(PYTHON) test_pythonlib.py --bytecode-1.4 $(PYTHON) test_pythonlib.py --bytecode-1.4

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -78,7 +78,7 @@ for vers in (2.7, 3.4, 3.5, 3.6):
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers) test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
pass pass
for vers in (1.4, 1.5, for vers in (1.3, 1.4, 1.5,
2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.0, 3.1, 3.2, 3.3, 3.0, 3.1, 3.2, 3.3,
3.4, 3.5, 3.6, 3.7, 'pypy3.2', 'pypy2.7'): 3.4, 3.5, 3.6, 3.7, 'pypy3.2', 'pypy2.7'):

View File

@@ -621,7 +621,13 @@ def get_python_parser(
if version < 3.0: if version < 3.0:
if version < 2.2: if version < 2.2:
if version == 1.4: if version == 1.3:
import uncompyle6.parsers.parse13 as parse13
if compile_mode == 'exec':
p = parse13.Python14Parser(debug_parser)
else:
p = parse13.Python14ParserSingle(debug_parser)
elif version == 1.4:
import uncompyle6.parsers.parse14 as parse14 import uncompyle6.parsers.parse14 as parse14
if compile_mode == 'exec': if compile_mode == 'exec':
p = parse14.Python14Parser(debug_parser) p = parse14.Python14Parser(debug_parser)

View File

@@ -0,0 +1,49 @@
# Copyright (c) 2018 Rocky Bernstein
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse14 import Python14Parser
class Python13Parser(Python14Parser):
def p_misc13(self, args):
"""
# Nothing here yet, but will need to add LOAD_GLOBALS
"""
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
super(Python13Parser, self).__init__(debug_parser)
self.customized = {}
# def customize_grammar_rules(self, tokens, customize):
# super(Python13Parser, self).customize_grammar_rules(tokens, customize)
# self.remove_rules("""
# whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt
# jb_pop
# POP_BLOCK else_suitel COME_FROM
# """)
# self.check_reduce['doc_junk'] = 'tokens'
# def reduce_is_invalid(self, rule, ast, tokens, first, last):
# invalid = super(Python14Parser,
# self).reduce_is_invalid(rule, ast,
# tokens, first, last)
# if invalid or tokens is None:
# return invalid
# if rule[0] == 'doc_junk':
# return not isinstance(tokens[first].pattr, str)
class Python13ParserSingle(Python13Parser, PythonParserSingle):
pass
if __name__ == '__main__':
# Check grammar
p = Python13Parser()
p.check_grammar()
p.dump_grammar()
# local variables:
# tab-width: 4

View File

@@ -8,12 +8,11 @@ class Python14Parser(Python15Parser):
def p_misc14(self, args): def p_misc14(self, args):
""" """
# Nothing here yet, but will need to add UNARY_CALL, BINARY_CALL, # Not much here yet, but will probably need to add UNARY_CALL, BINARY_CALL,
# RAISE_EXCEPTION, BUILD_FUNCTION, UNPACK_ARG, UNPACK_VARARG, LOAD_LOCAL, # RAISE_EXCEPTION, BUILD_FUNCTION, UNPACK_ARG, UNPACK_VARARG, LOAD_LOCAL,
# SET_FUNC_ARGS, and RESERVE_FAST # SET_FUNC_ARGS, and RESERVE_FAST
# FIXME: should check that this indeed around __doc__ # Not strictly needed, but tidies up output
# Possibly not strictly needed
stmt ::= doc_junk stmt ::= doc_junk
doc_junk ::= LOAD_CONST POP_TOP doc_junk ::= LOAD_CONST POP_TOP

View File

@@ -37,7 +37,7 @@ from xdis.util import code2num
# The byte code versions we support. # The byte code versions we support.
# Note: these all have to be floats # Note: these all have to be floats
PYTHON_VERSIONS = frozenset((1.4, 1.5, PYTHON_VERSIONS = frozenset((1.3, 1.4, 1.5,
2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7)) 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7))

View File

@@ -0,0 +1,35 @@
# Copyright (c) 2018 by Rocky Bernstein
"""
Python 1.3 bytecode decompiler massaging.
This massages tokenized 1.3 bytecode to make it more amenable for
grammar parsing.
"""
import uncompyle6.scanners.scanner14 as scan
# from uncompyle6.scanners.scanner26 import ingest as ingest26
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_13
JUMP_OPS = opcode_13.JUMP_OPS
# We base this off of 1.4 instead of the other way around
# because we cleaned things up this way.
# The history is that 2.7 support is the cleanest,
# then from that we got 2.6 and so on.
class Scanner13(scan.Scanner14):
def __init__(self, show_asm=False):
scan.Scanner14.__init__(self, show_asm)
self.opc = opcode_13
self.opname = opcode_13.opname
self.version = 1.3
return
# def ingest22(self, co, classname=None, code_objects={}, show_asm=None):
# tokens, customize = self.parent_ingest(co, classname, code_objects, show_asm)
# tokens = [t for t in tokens if t.kind != 'SET_LINENO']
# # for t in tokens:
# # print(t)
#
# return tokens, customize