You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Add Python 1.3 decompilation ..
Reduced checking via "make check-short"
This commit is contained in:
@@ -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?
|
||||||
---------
|
---------
|
||||||
|
@@ -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
|
||||||
|
BIN
test/bytecode_1.3/test_builtin.pyc
Normal file
BIN
test/bytecode_1.3/test_builtin.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_exceptions.pyc
Normal file
BIN
test/bytecode_1.3/test_exceptions.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_grammar.pyc
Normal file
BIN
test/bytecode_1.3/test_grammar.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/test_operations.pyc
Normal file
BIN
test/bytecode_1.3/test_operations.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_1.3/testall.pyc
Normal file
BIN
test/bytecode_1.3/testall.pyc
Normal file
Binary file not shown.
@@ -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'):
|
||||||
|
@@ -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)
|
||||||
|
49
uncompyle6/parsers/parse13.py
Normal file
49
uncompyle6/parsers/parse13.py
Normal 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
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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))
|
||||||
|
|
||||||
|
35
uncompyle6/scanners/scanner13.py
Normal file
35
uncompyle6/scanners/scanner13.py
Normal 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
|
Reference in New Issue
Block a user