From ef30d16b589724780d91a2943004bb475d43d051 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Mon, 27 Jul 2009 00:30:31 +0000 Subject: [PATCH] Fixed crashes for files with certain unsupported opcodes --- ASTree.cpp | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/ASTree.cpp b/ASTree.cpp index 0663283..417cc0d 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -8,6 +8,10 @@ #define PY_2000 0x2000 #define PY_3000 0x3000 +/* Use this to determine if an error occurred (and therefore, if we should + * avoid cleaning the output tree) */ +static bool cleanBuild; + PycRef BuildFromCode(PycRef code, PycModule* mod) { PycBuffer source(code->code()->value(), code->code()->length()); @@ -148,10 +152,12 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) fprintf(stderr, "Unsupported opcode: %s\n", Py2k::OpcodeNames[opcode & 0xFF]); else if (mod->majorVer() == 3) fprintf(stderr, "Unsupported opcode: %s\n", Py3k::OpcodeNames[opcode & 0xFF]); + cleanBuild = false; return new ASTNodeList(lines); } } + cleanBuild = true; return new ASTNodeList(lines); } @@ -269,29 +275,31 @@ void decompyle(PycRef code, PycModule* mod, int indent) { PycRef source = BuildFromCode(code, mod); - // The Python compiler adds some stuff that we don't really care - // about, and would add extra code for re-compilation anyway. - // We strip these lines out here, and then add a "pass" statement - // if the cleaned up code is empty - PycRef clean = source.cast(); - if (clean->nodes().front()->type() == ASTNode::NODE_STORE) { - PycRef store = clean->nodes().front().cast(); - if (store->src()->type() == ASTNode::NODE_NAME && - store->dest()->type() == ASTNode::NODE_NAME) { - PycRef src = store->src().cast(); - PycRef dest = store->dest().cast(); - if (src->name().size() == 1 && dest->name().size() == 1 && - src->name().front()->isEqual("__name__") && - dest->name().front()->isEqual("__module__")) { - // __module__ = __name__ - clean->removeFirst(); + if (cleanBuild) { + // The Python compiler adds some stuff that we don't really care + // about, and would add extra code for re-compilation anyway. + // We strip these lines out here, and then add a "pass" statement + // if the cleaned up code is empty + PycRef clean = source.cast(); + if (clean->nodes().front()->type() == ASTNode::NODE_STORE) { + PycRef store = clean->nodes().front().cast(); + if (store->src()->type() == ASTNode::NODE_NAME && + store->dest()->type() == ASTNode::NODE_NAME) { + PycRef src = store->src().cast(); + PycRef dest = store->dest().cast(); + if (src->name().size() == 1 && dest->name().size() == 1 && + src->name().front()->isEqual("__name__") && + dest->name().front()->isEqual("__module__")) { + // __module__ = __name__ + clean->removeFirst(); + } } } - } - clean->removeLast(); // Always an extraneous return statement + clean->removeLast(); // Always an extraneous return statement - if (clean->nodes().size() == 0) - clean->append(new ASTNode(ASTNode::NODE_PASS)); + if (clean->nodes().size() == 0) + clean->append(new ASTNode(ASTNode::NODE_PASS)); + } print_src(source, mod, indent); }