-
-
Notifications
You must be signed in to change notification settings - Fork 413
Fixing Issue #150
I'm going to start documenting how I fix bugs in case others want to also do so. Issue 150 wasn't all that interesting, but still you might be able to get a sense of the tools and techniques used...
Here are the steps I have took to address issue #150
Step one is get a small test case and compile it. The test case provided in the issue was:
def func(a):
if a:
return True
something_never_run()
To compile it one can use the compile-file.py program in python-uncompyle6/test/stdlib
$ cd test/stdlib
$ pyenv 2.7.14
$ ./compile-file.py /tmp/issue-150.py
compiling /tmp/issue-150.py to /tmp/issue-150-2.7.pyc
Let's get detailed information in decomplation: assembly code, grammar reductions and the AST tree (which will fail below):
$ ../../bin/uncompyle6 -agT /tmp/issue-150-2.7.pyc > /tmp/issue-150-bad.log 2>&1
Looking at /tmp/issue-150-bad.log
we see:
L. 4: 10 assert_expr ::= expr (6)
L. 4: 10-16 call_stmt ::= expr POP_TOP (7)
L. 4: 10 stmt ::= call_stmt (7)
L. 3: 6-16 _stmts ::= _stmts stmt (7)
Reduce _stmts invalid by check
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Stacks of completed symbols:
LOAD_FAST .
LOAD_FAST . FOR_ITER store comp_iter JUMP_BACK
LOAD_GLOBAL .
It so happens that uncompyle2
decompiles correctly. So let's run that
and compare the grammar. The option that corresponds to t
in uncompyle2
is --showast
:
$ uncompyle2 --showast /tmp/issue-150-2.7.pyc > /tmp/issue-150-good.log
Looking at the tree for that we see:
c_stmts_opt
c_stmts
_stmts
stmt
So see if that "invalid reduction" rule is right. I removed the check from uncompyle6/parsers/parse2.py and this then worked.
Looking at the git log for the change with SHA 1e324e0e8db0d97c1ea63c577805a7b00720b83d
I read
scanner2.py: check that return stmt is last in list. (May change)
It looks to me then that this change was erroneous. In this commit you'll find that two Python 2.6 tests were added. To make sure those still work with the change. I ran inside test
:
make check-bytecode-2.6
But a full make check from the root uncompyle6 directory is done for final measure.
Lastly, we add a new test case for this particular code. Run inside test
directory::
$ cp /tmp/issue-150.py simple_source/bug27+/05_deadcode.py
$ git add simple_source/bug27+/05_deadcode.py
$ ./add-test.py simple_source/bug27+/05_deadcode.py
$ git add -f bytecode_2.7/05_deadcode.pyc