From 8f29c8f8dbfdee29c410793dabd9a9f73bd83a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 28 Aug 2016 19:55:33 +0200 Subject: [PATCH] AS3 p-code block ends like in RabcDasm --- .../decompiler/flash/abc/avm2/AVM2Code.java | 46 +++++-------------- .../abc/avm2/parser/pcode/ASM3Parser.java | 17 ++++++- .../flash/abc/types/MethodBody.java | 4 +- .../flash/abc/types/traits/Trait.java | 2 +- .../flash/ActionScript3DeobfuscatorTest.java | 2 +- .../flash/gui/abc/ASMSourceEditorPane.java | 5 +- .../gui/abc/SlotConstTraitDetailPanel.java | 1 + 7 files changed, 36 insertions(+), 41 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index ac7f5079a..23bda7014 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1152,45 +1152,15 @@ public class AVM2Code implements Cloneable { public String toASMSource(AVM2ConstantPool constants) { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toASMSource(constants, null, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); + toASMSource(constants, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); return writer.toString(); } - public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, ScriptExportMode exportMode, GraphTextWriter writer) { - return toASMSource(constants, trait, info, body, new ArrayList<>(), exportMode, writer); + public GraphTextWriter toASMSource(AVM2ConstantPool constants, MethodInfo info, MethodBody body, ScriptExportMode exportMode, GraphTextWriter writer) { + return toASMSource(constants, info, body, new ArrayList<>(), exportMode, writer); } - public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List outputMap, ScriptExportMode exportMode, GraphTextWriter writer) { - if (trait != null) { - if (trait instanceof TraitFunction) { - TraitFunction tf = (TraitFunction) trait; - writer.appendNoHilight("trait "); - writer.hilightSpecial("function ", HighlightSpecialType.TRAIT_TYPE); - writer.hilightSpecial(constants.multinameToString(tf.name_index), HighlightSpecialType.TRAIT_NAME); - writer.appendNoHilight(" slotid "); - writer.hilightSpecial("" + tf.slot_id, HighlightSpecialType.SLOT_ID); - writer.newLine(); - } - if (trait instanceof TraitMethodGetterSetter) { - TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; - writer.appendNoHilight("trait "); - switch (tm.kindType) { - case Trait.TRAIT_METHOD: - writer.hilightSpecial("method ", HighlightSpecialType.TRAIT_TYPE); - break; - case Trait.TRAIT_GETTER: - writer.hilightSpecial("getter ", HighlightSpecialType.TRAIT_TYPE); - break; - case Trait.TRAIT_SETTER: - writer.hilightSpecial("setter ", HighlightSpecialType.TRAIT_TYPE); - break; - } - writer.hilightSpecial(constants.multinameToString(tm.name_index), HighlightSpecialType.TRAIT_NAME); - writer.appendNoHilight(" dispid "); - writer.hilightSpecial("" + tm.disp_id, HighlightSpecialType.DISP_ID); - writer.newLine(); - } - } + public GraphTextWriter toASMSource(AVM2ConstantPool constants, MethodInfo info, MethodBody body, List outputMap, ScriptExportMode exportMode, GraphTextWriter writer) { if (info != null) { writer.appendNoHilight("method").newLine(); @@ -1317,7 +1287,6 @@ public class AVM2Code implements Cloneable { writer.newLine(); writer.appendNoHilight("code").newLine(); - int ip = 0; int largeLimit = 20000; boolean markOffsets = code.size() <= largeLimit; @@ -1362,6 +1331,13 @@ public class AVM2Code implements Cloneable { } else if (exportMode == ScriptExportMode.CONSTANTS) { writer.appendNoHilight("Constant export mode is not supported.").newLine(); } + writer.appendNoHilight("end ; code").newLine(); + if (body != null) { + writer.appendNoHilight("end ; body").newLine(); + } + if (info != null) { + writer.appendNoHilight("end ; method").newLine(); + } return writer; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java index cf5fdf203..73a9fd38b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java @@ -572,7 +572,8 @@ public class ASM3Parser { public static AVM2Code parse(ABC abc, Reader reader, Trait trait, MissingSymbolHandler missingHandler, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException { AVM2ConstantPool constants = abc.constants; AVM2Code code = new AVM2Code(); - + int openedBlocks = 0; + boolean autoCloseBlocks = false; List offsetItems = new ArrayList<>(); List labelItems = new ArrayList<>(); List exceptions = new ArrayList<>(); @@ -594,9 +595,11 @@ public class ASM3Parser { do { symb = lexer.lex(); if (Arrays.asList(ParsedSymbol.TYPE_KEYWORD_BODY, ParsedSymbol.TYPE_KEYWORD_CODE, ParsedSymbol.TYPE_KEYWORD_METHOD).contains(symb.type)) { + openedBlocks++; continue; } if (symb.type == ParsedSymbol.TYPE_KEYWORD_TRAIT) { + openedBlocks++; if (trait == null) { throw new AVM2ParseException("No trait expected", lexer.yyline()); } @@ -790,6 +793,14 @@ public class ASM3Parser { } continue; } + if (symb.type == ParsedSymbol.TYPE_KEYWORD_END) { + if (openedBlocks > 0) { + openedBlocks--; + } else { + throw new AVM2ParseException("End block encountered but there is no block opened", lexer.yyline()); + } + continue; + } if (symb.type == ParsedSymbol.TYPE_INSTRUCTION_NAME) { if (((String) symb.value).toLowerCase(Locale.ENGLISH).equals("exception")) { ParsedSymbol exIndex = lexer.lex(); @@ -1055,6 +1066,10 @@ public class ASM3Parser { } } while (symb.type != ParsedSymbol.TYPE_EOF); + if (!autoCloseBlocks && openedBlocks > 0) { + throw new AVM2ParseException("End of the block expected: " + openedBlocks + "x", lexer.yyline()); + } + code.compact(); for (LabelItem li : labelItems) { int ind; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index de2f8c1da..6f0b5c436 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -294,7 +294,7 @@ public final class MethodBody implements Cloneable { System.err.println("Decompiling " + path); } if (exportMode != ScriptExportMode.AS) { - getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); + getCode().toASMSource(abc.constants, abc.method_info.get(this.method_info), this, exportMode, writer); } else { if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); @@ -347,7 +347,7 @@ public final class MethodBody implements Cloneable { public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames) throws InterruptedException { if (exportMode != ScriptExportMode.AS) { - getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); + getCode().toASMSource(abc.constants, abc.method_info.get(this.method_info), this, exportMode, writer); } else { if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { //writer.startMethod(this.method_info); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index f06b3990f..bc95e296d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -434,7 +434,7 @@ public abstract class Trait implements Cloneable, Serializable { writer.newLine(); } } - writer.append("end ;metadata"); + writer.append("end ; metadata"); } } return writer; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index f21086212..4a08ccad0 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -88,7 +88,7 @@ public class ActionScript3DeobfuscatorTest extends ActionScript2TestBase { b.setCode(code); new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps("test", 0, true, 0, abc, null, 0, b); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - code.toASMSource(abc.constants, null, new MethodInfo(), new MethodBody(abc, new Traits(), new byte[0], new ABCException[0]), ScriptExportMode.PCODE, writer); + code.toASMSource(abc.constants, new MethodInfo(), new MethodBody(abc, new Traits(), new byte[0], new ABCException[0]), ScriptExportMode.PCODE, writer); String ret = writer.toString(); return ret.substring(ret.lastIndexOf("code\r\n") + 6); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java index 500dd3217..08e80dfcb 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java @@ -118,7 +118,10 @@ public class ASMSourceEditorPane extends DebuggableEditorPane implements CaretLi if (trait != null && exportMode != ScriptExportMode.AS && exportMode != ScriptExportMode.AS_METHOD_STUBS) { trait.convertTraitHeader(abc, writer); } - abc.bodies.get(bodyIndex).getCode().toASMSource(abc.constants, trait, abc.method_info.get(abc.bodies.get(bodyIndex).method_info), abc.bodies.get(bodyIndex), exportMode, writer); + abc.bodies.get(bodyIndex).getCode().toASMSource(abc.constants, abc.method_info.get(abc.bodies.get(bodyIndex).method_info), abc.bodies.get(bodyIndex), exportMode, writer); + if (trait != null) { + writer.appendNoHilight("end ; trait").newLine(); + } return new HighlightedText(writer); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java index 2da1be684..ef537dc32 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java @@ -102,6 +102,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { this.trait = trait; HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); trait.convertTraitHeader(abc, writer); + writer.appendNoHilight("end ; trait"); String s = writer.toString(); specialHilights = writer.specialHilights; showWarning = trait.isConst() || isStatic;