From 599d22bb6e3d47ea46472dc7df0bc92d1326cba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 21 Feb 2021 16:55:40 +0100 Subject: [PATCH] AS3 P-code editation checking all referenced labels exist Fixed: AS3 P-code editation - only first try offset was saved when multiple try with same label --- CHANGELOG.md | 2 + .../abc/avm2/parser/pcode/ASM3Parser.java | 83 +++++++++++-------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5176d125a..7a8d0289c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - Japanese translation - #428, #583, #1373 Exporting PDFs with selectable text - Goto address dialog in Hex view (Ctrl+G or via context menu) +- AS3 P-code editation checking all referenced labels exist ### Fixed - #1298 AS1/2 properly decompiled setProperty/getProperty @@ -38,6 +39,7 @@ All notable changes to this project will be documented in this file. - #1610 AS3 P-code editation - true/false/undefined/null has value_index same as value_kind - Ribbon stealing focus when pressing Alt (for example in editors) - Focused byte barely visible in hex view +- AS3 P-code editation - only first try offset was saved when multiple try with same label ### Changed - #1565, #1407, #1350 On BinaryData SWF save, parent SWF is saved 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 f5af84295..7518cc170 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 @@ -66,17 +66,20 @@ public class ASM3Parser { public int insOperandIndex; - public OffsetItem(String label, long insOffset, int insOperandIndex) { + public int line; + + public OffsetItem(String label, long insOffset, int insOperandIndex, int line) { this.label = label; this.insPosition = insOffset; this.insOperandIndex = insOperandIndex; + this.line = line; } } private static class CaseOffsetItem extends OffsetItem { - public CaseOffsetItem(String label, long insOffset, int insOperandIndex) { - super(label, insOffset, insOperandIndex); + public CaseOffsetItem(String label, long insOffset, int insOperandIndex, int line) { + super(label, insOffset, insOperandIndex, line); } } @@ -90,6 +93,12 @@ public class ASM3Parser { this.label = label; this.offset = offset; } + + @Override + public String toString() { + return label + " at address " + offset; + } + } public static AVM2Code parse(ABC abc, Reader reader, Trait trait, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException { @@ -617,7 +626,7 @@ public class ASM3Parser { AVM2Code code = new AVM2Code(); boolean autoCloseBlocks = true; //TODO? Put to false. But how about old imports? List offsetItems = new ArrayList<>(); - List labelItems = new ArrayList<>(); + Map labelToOffset = new HashMap<>(); List exceptions = new ArrayList<>(); List exceptionIndices = new ArrayList<>(); int offset = 0; @@ -629,6 +638,7 @@ public class ASM3Parser { List exceptionsFrom = new ArrayList<>(); List exceptionsTo = new ArrayList<>(); List exceptionsTargets = new ArrayList<>(); + List exceptionLines = new ArrayList<>(); info.flags = 0; info.name_index = 0; List paramTypes = new ArrayList<>(); @@ -787,6 +797,7 @@ public class ASM3Parser { continue; } if (symb.type == ParsedSymbol.TYPE_KEYWORD_TRY) { + exceptionLines.add(lexer.yyline()); expected(ParsedSymbol.TYPE_KEYWORD_FROM, "From", lexer); symb = lexer.lex(); expected(symb, ParsedSymbol.TYPE_IDENTIFIER, "Identifier"); @@ -1042,7 +1053,7 @@ public class ASM3Parser { break; case AVM2Code.DAT_OFFSET: if (parsedOperand.type == ParsedSymbol.TYPE_IDENTIFIER) { - offsetItems.add(new OffsetItem((String) parsedOperand.value, code.code.size(), i)); + offsetItems.add(new OffsetItem((String) parsedOperand.value, code.code.size(), i, lexer.yyline())); operandsList.add(0); } else { throw new AVM2ParseException("Offset expected", lexer.yyline()); @@ -1050,7 +1061,7 @@ public class ASM3Parser { break; case AVM2Code.DAT_CASE_BASEOFFSET: if (parsedOperand.type == ParsedSymbol.TYPE_IDENTIFIER) { - offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i)); + offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i, lexer.yyline())); operandsList.add(0); } else { throw new AVM2ParseException("Offset expected", lexer.yyline()); @@ -1063,9 +1074,9 @@ public class ASM3Parser { int c = 0; while (parsedOperand.type == ParsedSymbol.TYPE_IDENTIFIER) { - offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i + (c + 1))); + offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i + (c + 1), lexer.yyline())); c++; - parsedOperand = lexer.lex(); + parsedOperand = lexer.lex(); if (parsedOperand.type == ParsedSymbol.TYPE_BRACKET_CLOSE) { break; } @@ -1094,7 +1105,7 @@ public class ASM3Parser { parsedOperand = lexer.lex(); } if (parsedOperand.type == ParsedSymbol.TYPE_IDENTIFIER) { - offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i + (c + 1))); + offsetItems.add(new CaseOffsetItem((String) parsedOperand.value, code.code.size(), i + (c + 1), lexer.yyline())); operandsList.add(0); } else { throw new AVM2ParseException("Offset expected", lexer.yyline()); @@ -1150,7 +1161,7 @@ public class ASM3Parser { throw new AVM2ParseException("Invalid instruction name:" + (String) symb.value, lexer.yyline()); } } else if (symb.type == ParsedSymbol.TYPE_LABEL) { - labelItems.add(new LabelItem((String) symb.value, offset)); + labelToOffset.put((String) symb.value, offset); } else { throw new AVM2ParseException("Unexpected symbol", lexer.yyline()); @@ -1162,40 +1173,40 @@ public class ASM3Parser { } code.compact(); - for (LabelItem li : labelItems) { - int ind; - ind = exceptionsFrom.indexOf(li.label); - if (ind > -1) { - exceptions.get(ind).start = li.offset; - } - ind = exceptionsTo.indexOf(li.label); - if (ind > -1) { - exceptions.get(ind).end = li.offset; + for (int i = 0; i < exceptions.size(); i++) { + if (!labelToOffset.containsKey(exceptionsFrom.get(i))) { + throw new AVM2ParseException("Label " + exceptionsFrom.get(i) + " for exception from not defined", exceptionLines.get(i)); } + exceptions.get(i).start = labelToOffset.get(exceptionsFrom.get(i)); - ind = exceptionsTargets.indexOf(li.label); - if (ind > -1) { - exceptions.get(ind).target = li.offset; + if (!labelToOffset.containsKey(exceptionsTo.get(i))) { + throw new AVM2ParseException("Label " + exceptionsTo.get(i) + " for exception to not defined", exceptionLines.get(i)); } + exceptions.get(i).end = labelToOffset.get(exceptionsTo.get(i)); + + if (!labelToOffset.containsKey(exceptionsTargets.get(i))) { + throw new AVM2ParseException("Label " + exceptionsTargets.get(i) + "for exception target not defined", exceptionLines.get(i)); + } + exceptions.get(i).target = labelToOffset.get(exceptionsTargets.get(i)); } for (OffsetItem oi : offsetItems) { - for (LabelItem li : labelItems) { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - if (oi.label.equals(li.label)) { - AVM2Instruction ins = code.code.get((int) oi.insPosition); - int relOffset; - if (oi instanceof CaseOffsetItem) { - relOffset = li.offset - (int) ins.getAddress(); - } else { - relOffset = li.offset - ((int) ins.getAddress() + ins.getBytesLength()); - } - ins.operands[oi.insOperandIndex] = relOffset; - } + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); } + if (!labelToOffset.containsKey(oi.label)) { + throw new AVM2ParseException("Label " + oi.label + " not defined", oi.line); + } + int labelOffset = labelToOffset.get(oi.label); + AVM2Instruction ins = code.code.get((int) oi.insPosition); + int relOffset; + if (oi instanceof CaseOffsetItem) { + relOffset = labelOffset - (int) ins.getAddress(); + } else { + relOffset = labelOffset - ((int) ins.getAddress() + ins.getBytesLength()); + } + ins.operands[oi.insOperandIndex] = relOffset; } body.exceptions = new ABCException[exceptions.size()]; for (int e = 0; e < exceptions.size(); e++) {