mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-31 08:16:44 +00:00
Fixed: #2486 AS3 switches detection in some cases
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2025 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This will fix some if(false) in Flex code in switch default statement.
|
||||
* It is not a real deobufscation, just fix for specific case.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorPushFalseIfFalse extends SWFDecompilerAdapter {
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
Map<Integer, List<Integer>> refs = body.getCode().visitCode(body);
|
||||
AVM2Code code = body.getCode();
|
||||
for (int ip = 1; ip < code.code.size(); ip++) {
|
||||
AVM2Instruction ins = code.code.get(ip);
|
||||
AVM2Instruction insPrev = code.code.get(ip - 1);
|
||||
if (!(ins.definition instanceof IfFalseIns)) {
|
||||
continue;
|
||||
}
|
||||
if (!(insPrev.definition instanceof PushFalseIns)) {
|
||||
continue;
|
||||
}
|
||||
if (refs.containsKey(ip) && refs.get(ip).size() > 1) {
|
||||
continue;
|
||||
}
|
||||
insPrev.definition = new NopIns();
|
||||
ins.definition = new JumpIns();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,9 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns;
|
||||
@@ -44,6 +46,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.Dec
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.IncLocalPIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns;
|
||||
@@ -84,6 +87,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.EqAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.NeqAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictEqAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictNeqAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
@@ -110,13 +114,17 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.DefaultItem;
|
||||
import com.jpexs.decompiler.graph.model.ExitItem;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.IntegerValueItem;
|
||||
import com.jpexs.decompiler.graph.model.IntegerValueTypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LoopItem;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.OrItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.decompiler.graph.model.SwitchItem;
|
||||
import com.jpexs.decompiler.graph.model.TernarOpItem;
|
||||
@@ -129,6 +137,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -1735,11 +1744,8 @@ public class AVM2Graph extends Graph {
|
||||
Loop currentLoop, int staticOperation, String path) throws InterruptedException {
|
||||
List<GraphTargetItem> ret = null;
|
||||
|
||||
/*if (ret != null) {
|
||||
return ret;
|
||||
}*/
|
||||
//Detect switch
|
||||
if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqAVM2Item)) {
|
||||
if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && ((stack.peek() instanceof StrictEqAVM2Item) || (stack.peek() instanceof StrictNeqAVM2Item))) {
|
||||
GraphSourceItem switchStartItem = code.get(part.start);
|
||||
|
||||
GraphTargetItem switchedObject = null;
|
||||
@@ -1750,29 +1756,82 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
List<GraphTargetItem> caseValuesMapLeft = new ArrayList<>();
|
||||
List<GraphTargetItem> caseValuesMapRight = new ArrayList<>();
|
||||
List<List<GraphTargetItem>> outs = new ArrayList<>();
|
||||
|
||||
StrictEqAVM2Item set = (StrictEqAVM2Item) stack.pop();
|
||||
StrictEqAVM2Item firstSet = set;
|
||||
outs.add(new ArrayList<>());
|
||||
|
||||
BinaryOpItem set = (BinaryOpItem) stack.pop();
|
||||
BinaryOpItem firstSet = set;
|
||||
caseValuesMapLeft.add(set.leftSide);
|
||||
caseValuesMapRight.add(set.rightSide);
|
||||
|
||||
int branchNum;
|
||||
|
||||
GraphPart origPart = part;
|
||||
List<GraphPart> caseBodyParts = new ArrayList<>();
|
||||
caseBodyParts.add(part.nextParts.get(0));
|
||||
|
||||
if (((AVM2Instruction) code.get(part.end)).definition instanceof IfStrictNeIns) {
|
||||
branchNum = 0;
|
||||
caseBodyParts.add(part.nextParts.get(1));
|
||||
} else {
|
||||
branchNum = 1;
|
||||
caseBodyParts.add(part.nextParts.get(0));
|
||||
}
|
||||
GraphTargetItem top = null;
|
||||
int cnt = 1;
|
||||
int branchCount = 2;
|
||||
try {
|
||||
while (part.nextParts.size() > 1
|
||||
&& part.nextParts.get(1).getHeight() > 1
|
||||
&& ((AVM2Instruction) code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end)).definition instanceof IfStrictEqIns
|
||||
&& ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqAVM2Item)) {
|
||||
cnt++;
|
||||
part = part.nextParts.get(1);
|
||||
caseBodyParts.add(part.nextParts.get(0));
|
||||
while (true) {
|
||||
List<GraphTargetItem> out = new ArrayList<>();
|
||||
//Special: In Flex (not air) there are these blocks sometimes:
|
||||
// if(false) {
|
||||
// §§push(5);
|
||||
// break;
|
||||
//}
|
||||
//AVM2DeobfuscatorPushFalseIfFalse changes it to
|
||||
// nop
|
||||
// jump
|
||||
// (to first case to work)
|
||||
if (part.nextParts.size() == branchCount
|
||||
&& part.nextParts.get(branchNum).getHeight() == 2
|
||||
&& ((AVM2Instruction) code.get(part.nextParts.get(branchNum).start >= code.size() ? code.size() - 1 : part.nextParts.get(branchNum).start)).definition instanceof NopIns
|
||||
&& ((AVM2Instruction) code.get(part.nextParts.get(branchNum).end >= code.size() ? code.size() - 1 : part.nextParts.get(branchNum).end)).definition instanceof JumpIns) {
|
||||
part = part.nextParts.get(branchNum);
|
||||
branchNum = 0;
|
||||
branchCount = 1;
|
||||
} else if (part.nextParts.size() == branchCount
|
||||
&& part.nextParts.get(branchNum).getHeight() > 1
|
||||
&& ((AVM2Instruction) code.get(part.nextParts.get(branchNum).end >= code.size() ? code.size() - 1 : part.nextParts.get(branchNum).end)).definition instanceof IfStrictEqIns
|
||||
&& ((top = translatePartGetStack(localData, part.nextParts.get(branchNum), stack, staticOperation, out)) instanceof StrictEqAVM2Item)) {
|
||||
cnt++;
|
||||
part = part.nextParts.get(branchNum);
|
||||
caseBodyParts.add(part.nextParts.get(0));
|
||||
branchNum = 1;
|
||||
|
||||
set = (StrictEqAVM2Item) top;
|
||||
caseValuesMapLeft.add(set.leftSide);
|
||||
caseValuesMapRight.add(set.rightSide);
|
||||
outs.add(out);
|
||||
out = new ArrayList<>();
|
||||
set = (StrictEqAVM2Item) top;
|
||||
caseValuesMapLeft.add(set.leftSide);
|
||||
caseValuesMapRight.add(set.rightSide);
|
||||
branchCount = 2;
|
||||
} else if (part.nextParts.size() == branchCount
|
||||
&& part.nextParts.get(branchNum).getHeight() > 1
|
||||
&& ((AVM2Instruction) code.get(part.nextParts.get(branchNum).end >= code.size() ? code.size() - 1 : part.nextParts.get(branchNum).end)).definition instanceof IfStrictNeIns
|
||||
&& ((top = translatePartGetStack(localData, part.nextParts.get(branchNum), stack, staticOperation, out)) instanceof StrictNeqAVM2Item)) {
|
||||
cnt++;
|
||||
part = part.nextParts.get(branchNum);
|
||||
caseBodyParts.add(part.nextParts.get(1));
|
||||
branchNum = 0;
|
||||
|
||||
outs.add(out);
|
||||
out = new ArrayList<>();
|
||||
set = (StrictNeqAVM2Item) top;
|
||||
caseValuesMapLeft.add(set.leftSide);
|
||||
caseValuesMapRight.add(set.rightSide);
|
||||
branchCount = 2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (GraphPartChangeException gpc) {
|
||||
//ignore
|
||||
@@ -1818,10 +1877,17 @@ public class AVM2Graph extends Graph {
|
||||
otherSide = caseValuesMapRight;
|
||||
}
|
||||
|
||||
for (int i = 0; i < caseValuesMap.size(); i++) {
|
||||
if (!outs.get(i).isEmpty()) {
|
||||
outs.get(i).add(caseValuesMap.get(i));
|
||||
caseValuesMap.set(i, new CommaExpressionItem(dialect, null, null, outs.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
if ((leftReg < 0 && rightReg < 0) || (cnt == 1)) {
|
||||
stack.push(firstSet);
|
||||
} else {
|
||||
part = part.nextParts.get(1);
|
||||
part = part.nextParts.get(branchNum);
|
||||
GraphPart defaultPart = part;
|
||||
if (code.size() > defaultPart.start && ((AVM2Instruction) code.get(defaultPart.start)).definition instanceof JumpIns
|
||||
&& defaultPart.refs.size() == 1
|
||||
@@ -2443,9 +2509,11 @@ public class AVM2Graph extends Graph {
|
||||
if (item instanceof IntegerValueAVM2Item) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
if ((item instanceof PushItem) && (item.value instanceof IntegerValueAVM2Item)) {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2454,6 +2522,159 @@ public class AVM2Graph extends Graph {
|
||||
if (debugDoNotProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
loopi:
|
||||
for (int i = 1 /*not first*/; i < list.size(); i++) {
|
||||
GraphTargetItem item = list.get(i);
|
||||
|
||||
GraphTargetItem prevItem = list.get(i - 1);
|
||||
if ((item instanceof SwitchItem) && (prevItem instanceof SwitchItem)) {
|
||||
SwitchItem thisSwitch = (SwitchItem) item;
|
||||
SwitchItem prevSwitch = (SwitchItem) prevItem;
|
||||
if (thisSwitch.switchedObject instanceof PopItem) {
|
||||
List<Integer> caseValues = new ArrayList<>();
|
||||
Map<Integer, GraphTargetItem> expressionsMap = new LinkedHashMap<>();
|
||||
List<GraphTargetItem> defaultCommands = null;
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
continue;
|
||||
}
|
||||
if (!(thisSwitch.caseValues.get(k) instanceof IntegerValueTypeItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
}
|
||||
|
||||
int defaultInt = -1;
|
||||
|
||||
for (int j = 0; j < prevSwitch.caseCommands.size(); j++) {
|
||||
|
||||
int valueIndex = prevSwitch.valuesMapping.indexOf(j);
|
||||
|
||||
if (valueIndex == -1) {
|
||||
continue loopi;
|
||||
}
|
||||
|
||||
GraphTargetItem currentExpression = prevSwitch.caseValues.get(valueIndex);
|
||||
|
||||
if (prevSwitch.caseCommands.get(j).size() > 2) {
|
||||
continue loopi;
|
||||
}
|
||||
int delta = 0;
|
||||
if (currentExpression instanceof DefaultItem && prevSwitch.caseCommands.size() >= 2) {
|
||||
//Special case - in flex (not air), the default clause has weird
|
||||
// if (false) {
|
||||
// §§push(5);
|
||||
// }
|
||||
// §§push(5);
|
||||
if (prevSwitch.caseCommands.get(j).get(0) instanceof IfItem) {
|
||||
IfItem ifi = (IfItem) prevSwitch.caseCommands.get(j).get(0);
|
||||
if (ifi.expression instanceof FalseItem) {
|
||||
delta++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == prevSwitch.caseCommands.size() - 1 && prevSwitch.caseCommands.get(j).size() == delta + 1) {
|
||||
//empty
|
||||
} else if (prevSwitch.caseCommands.get(j).size() != 2 + delta) {
|
||||
continue loopi;
|
||||
} else {
|
||||
if (!(prevSwitch.caseCommands.get(j).get(delta + 1) instanceof BreakItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
BreakItem br = (BreakItem) prevSwitch.caseCommands.get(j).get(delta + 1);
|
||||
if (br.loopId != prevSwitch.loop.id) {
|
||||
continue loopi;
|
||||
}
|
||||
}
|
||||
if (!(prevSwitch.caseCommands.get(j).get(delta) instanceof PushItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
PushItem pi = (PushItem) prevSwitch.caseCommands.get(j).get(delta);
|
||||
if (!(pi.value instanceof IntegerValueTypeItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
Integer pushedInt = ((IntegerValueTypeItem) pi.value).intValue();
|
||||
expressionsMap.put(pushedInt, currentExpression);
|
||||
if (currentExpression instanceof DefaultItem) {
|
||||
defaultInt = pushedInt;
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> thisExpressions = new ArrayList<>();
|
||||
int defaultIndex = -1;
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
defaultIndex = k;
|
||||
continue;
|
||||
}
|
||||
if (!(thisSwitch.caseValues.get(k) instanceof IntegerValueTypeItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
int cv = ((IntegerValueTypeItem) thisSwitch.caseValues.get(k)).intValue();
|
||||
if (!expressionsMap.containsKey(cv)) {
|
||||
continue loopi;
|
||||
}
|
||||
thisExpressions.add(cv);
|
||||
}
|
||||
|
||||
List<Integer> noCaseExpressions = new ArrayList<>();
|
||||
|
||||
for (int key : expressionsMap.keySet()) {
|
||||
if (!thisExpressions.contains(key)) {
|
||||
if (defaultIndex == -1 && defaultInt != key) {
|
||||
continue loopi;
|
||||
}
|
||||
noCaseExpressions.add(key);
|
||||
}
|
||||
}
|
||||
noCaseExpressions.sort(new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
int m = thisSwitch.valuesMapping.get(k);
|
||||
thisSwitch.caseValues.remove(k);
|
||||
thisSwitch.valuesMapping.remove(k);
|
||||
|
||||
for (int e : noCaseExpressions) {
|
||||
thisSwitch.caseValues.add(k, expressionsMap.get(e));
|
||||
thisSwitch.valuesMapping.add(k, m);
|
||||
k++;
|
||||
}
|
||||
k--;
|
||||
|
||||
boolean foundElsewhere = false;
|
||||
for (int h = 0; h < thisSwitch.valuesMapping.size(); h++) {
|
||||
if (thisSwitch.valuesMapping.get(h) == m) {
|
||||
foundElsewhere = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundElsewhere) {
|
||||
thisSwitch.caseCommands.remove(m);
|
||||
for (int h = 0; h < thisSwitch.valuesMapping.size(); h++) {
|
||||
if (thisSwitch.valuesMapping.get(h) > m) {
|
||||
thisSwitch.valuesMapping.set(h, thisSwitch.valuesMapping.get(h) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int cv = ((IntegerValueTypeItem) thisSwitch.caseValues.get(k)).intValue();
|
||||
thisSwitch.caseValues.set(k, expressionsMap.get(cv));
|
||||
}
|
||||
|
||||
thisSwitch.switchedObject = prevSwitch.switchedObject;
|
||||
list.remove(i - 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (level == 0) {
|
||||
if (!list.isEmpty()) {
|
||||
if (list.get(list.size() - 1) instanceof ReturnVoidAVM2Item) {
|
||||
@@ -2890,7 +3111,7 @@ public class AVM2Graph extends Graph {
|
||||
});
|
||||
i = newI.getVal();
|
||||
}
|
||||
*/
|
||||
*/
|
||||
//Handle for loops at the end:
|
||||
super.finalProcess(parent, list, level, localData, path);
|
||||
}
|
||||
@@ -2931,7 +3152,7 @@ public class AVM2Graph extends Graph {
|
||||
AVM2LocalData avm2LocalData = (AVM2LocalData) localData;
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(output.size() - 1);
|
||||
int setLocalIp = InstructionDefinition.getItemIp(avm2LocalData, setLocal);
|
||||
;
|
||||
|
||||
Set<Integer> allUsages = new HashSet<>(avm2LocalData.getSetLocalUsages(setLocalIp));
|
||||
boolean isOtherSideReg = false;
|
||||
for (GraphTargetItem otherSide : otherSides) {
|
||||
@@ -3263,5 +3484,5 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
return ternar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCodeException;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorPushFalseIfFalse;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
@@ -642,6 +643,11 @@ public final class MethodBody implements Cloneable {
|
||||
code.fixJumps(path, body);
|
||||
return body;
|
||||
}
|
||||
} else {
|
||||
//This needs to be done otherwise some switch testcases fail. (Flex)
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorPushFalseIfFalse")) {
|
||||
new AVM2DeobfuscatorPushFalseIfFalse().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, method_info, body);
|
||||
}
|
||||
}
|
||||
|
||||
lastConvertedBody = body;
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.BranchStackResistant;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
|
||||
import com.jpexs.decompiler.graph.model.CommentItem;
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.DefaultItem;
|
||||
import com.jpexs.decompiler.graph.model.DoWhileItem;
|
||||
@@ -1383,7 +1384,7 @@ public class Graph {
|
||||
* @param list List of GraphTargetItems
|
||||
* @param lastLoopId Last loop id
|
||||
*/
|
||||
protected final void processSwitches(List<GraphTargetItem> list, long lastLoopId) {
|
||||
protected void processSwitches(List<GraphTargetItem> list, long lastLoopId) {
|
||||
loopi:
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
GraphTargetItem item = list.get(i);
|
||||
@@ -2311,6 +2312,25 @@ public class Graph {
|
||||
translatePart(localData, part, stack, staticOperation, null);
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates part and get its stack with output
|
||||
*
|
||||
* @param localData Local data
|
||||
* @param part Part
|
||||
* @param stack Translate stack
|
||||
* @param staticOperation Unused
|
||||
* @return Top of the stack
|
||||
* @throws InterruptedException On interrupt
|
||||
* @throws GraphPartChangeException On graph part change
|
||||
*/
|
||||
//@SuppressWarnings("unchecked")
|
||||
protected final GraphTargetItem translatePartGetStack(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, List<GraphTargetItem> output) throws InterruptedException, GraphPartChangeException {
|
||||
stack = (TranslateStack) stack.clone();
|
||||
output.clear();
|
||||
output.addAll(translatePart(localData, part, stack, staticOperation, null));
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates part.
|
||||
@@ -3194,6 +3214,7 @@ public class Graph {
|
||||
if (debugPrintGraph) {
|
||||
System.err.println("Adding break");
|
||||
}
|
||||
makeAllCommands(ret, stack);
|
||||
ret.add(new BreakItem(dialect, null, localData.lineStartInstruction, el.id));
|
||||
return ret;
|
||||
}
|
||||
@@ -3204,6 +3225,7 @@ public class Graph {
|
||||
if (debugPrintGraph) {
|
||||
System.err.println("Adding precontinue");
|
||||
}
|
||||
makeAllCommands(ret, stack);
|
||||
ret.add(new ContinueItem(dialect, null, localData.lineStartInstruction, el.id));
|
||||
return ret;
|
||||
}
|
||||
@@ -3214,6 +3236,7 @@ public class Graph {
|
||||
if (debugPrintGraph) {
|
||||
System.err.println("Adding continue");
|
||||
}
|
||||
makeAllCommands(ret, stack);
|
||||
ret.add(new ContinueItem(dialect, null, localData.lineStartInstruction, el.id));
|
||||
return ret;
|
||||
}
|
||||
@@ -3267,8 +3290,10 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
if (code.size() <= part.start) {
|
||||
ret.add(new ScriptEndItem(dialect));
|
||||
if (code.size() <= part.start) {
|
||||
if (!(!ret.isEmpty() && ret.get(ret.size() - 1) instanceof ExitItem)) {
|
||||
ret.add(new ScriptEndItem(dialect));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3428,7 +3453,9 @@ public class Graph {
|
||||
}
|
||||
} while (exHappened);
|
||||
if ((part.end >= code.size() - 1) && getNextParts(localData, part).isEmpty()) {
|
||||
output.add(new ScriptEndItem(dialect));
|
||||
if (!(!output.isEmpty() && output.get(output.size() - 1) instanceof ExitItem)) {
|
||||
output.add(new ScriptEndItem(dialect));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4651,7 +4678,8 @@ public class Graph {
|
||||
stopPart2x.add(breakPart);
|
||||
stopPartKind2x.add(StopPartKind.OTHER);
|
||||
}
|
||||
currentCaseCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, stopPartKind2x, loops, throwStates, staticOperation, path);
|
||||
TranslateStack subStack = (TranslateStack) stack.clone();
|
||||
currentCaseCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, subStack, allParts, null, caseBodies.get(i), stopPart2x, stopPartKind2x, loops, throwStates, staticOperation, path);
|
||||
if (willHaveBreak) {
|
||||
if (!currentCaseCommands.isEmpty()) {
|
||||
GraphTargetItem last = currentCaseCommands.get(currentCaseCommands.size() - 1);
|
||||
@@ -4660,8 +4688,7 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
}
|
||||
caseCommands.add(currentCaseCommands);
|
||||
makeAllCommands(currentCaseCommands, stack);
|
||||
caseCommands.add(currentCaseCommands);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user