Open nobodxbodon opened 4 years ago
开始研究为何测试未过。先用--dump-python
看对应python代码:
>..\原始资料\可执行文件\ulang-0.2.2.exe --dump-python range.mulan
import sys
from math import *
ARGV = sys.argv[1:]
for n in range(0, 2 + 1):
print(n)
for n in range(1, 4):
print(n)
for n in range((-1), 4 + 1, 2):
print(n)
>__main__.exe --dump-python range.mulan
import sys
from math import *
ARGV = sys.argv[1:]
for n in range(0, 2 + 1):
print(n)
for n in range(1, 4):
print(n)
for n in range(len(1), 4 + 1, 2):
print(n)
可见-1错变成了len(1)。
ast信息比较长,可用--dump-ast
查看。对应差异部分(需要好的diff工具,因为是一整行,现在靠硬看对比)如下:
UnaryOp(op=USub(), operand=Num(n=1, lineno=8, col_offset=20), lineno=8, col_offset=19)
Call(func=Name(id='len', ctx=Load(), lineno=8, col_offset=19)
奇怪的多余return去掉后,此测试用例通过。
继续:
>__main__.exe --dump-python if_elif.mulan
import sys
from math import *
ARGV = sys.argv[1:]
if False:
if True:
pass
>..\原始资料\可执行文件\ulang-0.2.2.exe --dump-python if_elif.mulan
import sys
from math import *
ARGV = sys.argv[1:]
if False:
if True:
pass
elif True:
print(1)>__main__.exe --dump-python if_elif.mulan
import sys
from math import *
ARGV = sys.argv[1:]
if False:
if True:
pass
D:\study\mulan\bounty\测试代码>..\原始资料\可执行文件\ulang-0.2.2.exe --dump-python if_elif.mulan
import sys
from math import *
ARGV = sys.argv[1:]
if False:
if True:
pass
elif True:
print(1)
暂且不管为何要多个if true
(优化问题?)。好像elif语句完全被跳过了。再比ast:
orelse=[], lineno=1, col_offset=1
orelse=[If(test=NameConstant(value=True, lineno=3,
col_offset=8), body=[Expr(value=Call(func=Name(id='print', ctx=Load(), lineno=4, col_offset=5), args=[Num(n=1, lineno=4, col_offset=11)], keywords=[], lineno=4, col_offset=5), lineno=4, col_offset=5)], orelse=[], lineno=3, col_offset=3)], lineno=1, col_offset=1
orelse部分哪去了??貌似这段中,orelse的处理有问题:
@pg_.production('if_stmt : IF expr block elif_stmt')
@pg_.production('if_stmt : IF expr block ELSE block')
@pg_.production('elif_stmt : ')
@pg_.production('elif_stmt : ELIF expr block elif_stmt')
@pg_.production('elif_stmt : ELIF expr block ELSE block')
def if_stmt(self, p):
if len(p) == 0:
return []
elif len(p) == 5:
return ast.If(test=(p[1]),
body=(p[2]),
orelse=(p[(-1)]),
lineno=(self.getlineno(p)),
col_offset=(self.getcolno(p)))
else:
if not isinstance(p[(-1)], list):
p[-1] = []
return ast.If(test=(p[1]),
body=(p[2]),
orelse=(p[(-1)]),
lineno=(self.getlineno(p)),
col_offset=(self.getcolno(p)))
3月18日更:貌似修复了。
先看个貌似简单些的:
>__main__.exe --dump-python for_in.mulan
import sys
from math import *
ARGV = sys.argv[1:]
sum = 0
for n in range(5):
sum **= n
print(sum)
>..\原始资料\可执行文件\ulang-0.2.2.exe --dump-python for_in.mulan
import sys
from math import *
ARGV = sys.argv[1:]
sum = 0
for n in range(5):
sum += n
print(sum)
+=处理错误的样子。果然ast认错了:
op=Add()
op=Pow()
这个错误难道是反编译导致的吗?看起来倒是很“人造”。hmm希望所有错误都是这么“简单”。
nm 刚反应过来,这个绝对不可能是反编译的锅吧!哪个反编译能”智能“到把^
改成**
的??
下面这个lambda就比较巧了:
>__main__.exe --dump-ast lambda.mulan
> 路径略去\ulang\parser\core.py(845)bin_expr()
(Pdb)
直接定位到问题所在:
else:
breakpoint()
return ast.BinOp((p[0]),
为何会跑到bp呢?竟然又是个低级错误。难道真是反编译的锅?
type 错误也是神奇。比较 ast 后,发现是type_body
中只有第一块的内容。结果定位到这个缩进错误。
接下去,打算进行实现的摸索。首先完成一个最小的“交互环境”原型,使用最简单的 rply 规则,并生成 exe。
从源码生成可执行文件,使用原方案的 pyinstaller 或其他类似技术。 不需一开始就基于逆向工程,可以先新建一个最简原型(比如repl),进行技术验证。