Skip to content

Commit

Permalink
Fixed AS3 - getouterscope instruction support
Browse files Browse the repository at this point in the history
  • Loading branch information
jindrapetrik committed Mar 19, 2023
1 parent e8e2668 commit e9063e4
Show file tree
Hide file tree
Showing 30 changed files with 227 additions and 68 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ All notable changes to this project will be documented in this file.
- AS3 p-code docs - deldescendants, negate_p operands
- AS3 p-code - IGNORE_REST method flag incorrectly shown as EXPLICIT
- [#1989] AS3 - Slow deobfuscation (AVM2DeobfuscatorSimpleOld)
- AS3 p-code - getouterscope instruction docs
- AS3 - getouterscope instruction support

### Changed
- AS1/2/3 P-code - format Number values with EcmaScript toString function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class AVM2LocalData extends BaseLocalData {
public HashMap<Integer, GraphTargetItem> localRegs;

public ScopeStack scopeStack;

public ScopeStack localScopeStack;

public MethodBody methodBody;

Expand Down Expand Up @@ -145,6 +147,7 @@ public AVM2LocalData(AVM2LocalData localData) {
classIndex = localData.classIndex;
localRegs = localData.localRegs;
scopeStack = localData.scopeStack;
localScopeStack = localData.localScopeStack;
methodBody = localData.methodBody;
callStack = localData.callStack;
abc = localData.abc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns;
import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
Expand Down Expand Up @@ -197,14 +198,18 @@ public void convert(AbcIndexing abcIndex, final NulWriter writer, final List<Tra
scriptInitializerIsEmpty = !writer.getMark();

}
ScopeStack scopeStack = new ScopeStack();
scopeStack.push(new GlobalAVM2Item(null, null));


for (int t : traitIndices) {
Trait trait = traits.get(t);
Multiname name = trait.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
trait.convertPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel);
trait.convertPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack);
} else {
trait.convert(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel);
trait.convert(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@ public long getAddrThroughJumpAndDebugLine(long addr) throws ConvertException {
return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true)));
}

public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps) throws ConvertException, InterruptedException {
public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps) throws ConvertException, InterruptedException {
boolean debugMode = DEBUG_MODE;
if (debugMode) {
System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString());
Expand Down Expand Up @@ -1531,7 +1531,7 @@ public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody>
}

if (debugMode) {
System.err.println("translating ip " + ip + " ins " + ins.toString() + " stack:" + stack.toString() + " scopeStack:" + scopeStack.toString());
System.err.println("translating ip " + ip + " ins " + ins.toString() + " stack:" + stack.toString() + " localScopeStack:" + localScopeStack.toString());
}
if (ins.definition instanceof NewFunctionIns) {
if (ip + 1 <= end) {
Expand Down Expand Up @@ -1560,7 +1560,7 @@ public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody>
do {
AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null;
if (insAfter == null) {
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ip++;
break;
}
Expand All @@ -1582,14 +1582,14 @@ public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody>
//stack.add("(" + stack.pop() + ")||");
isAnd = false;
} else {
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ip++;
break;
//throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString());
}
} while (ins.definition instanceof DupIns);
} else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) {
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
//ip = end + 1;
break;
} else if (ins.definition instanceof NewFunctionIns) {
Expand All @@ -1607,12 +1607,12 @@ public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody>
}
AVM2Instruction psco = code.get(ip + 1 + plus);
if (psco.definition instanceof GetScopeObjectIns) {
if (psco.operands[0] == scopeStack.size() - 1) {
if (psco.operands[0] == localScopeStack.size() - 1) {
if (code.get(ip + plus + 2).definition instanceof SwapIns) {
if (code.get(ip + plus + 4).definition instanceof PopScopeIns) {
if (code.get(ip + plus + 3).definition instanceof SetPropertyIns) {
functionName = abc.constants.getMultiname(code.get(ip + plus + 3).operands[0]).getName(abc.constants, fullyQualifiedNames, true, true);
scopeStack.pop();// with
localScopeStack.pop();// with
output.remove(output.size() - 1); // with
ip = ip + plus + 4; // +1 below
}
Expand All @@ -1625,13 +1625,13 @@ public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody>
}
}
// What to do when hasDup is false?
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek();
nft.functionName = functionName;
ip++;
} else {
try {
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
} catch (RuntimeException re) {
/*String last="";
int len=5;
Expand Down Expand Up @@ -2059,11 +2059,10 @@ public List<GraphTargetItem> toGraphTargetItems(List<MethodBody> callStack, AbcI
localRegTypes.put(i + 1, AbcIndexing.multinameToType(abc.method_info.get(methodIndex).param_types[i], abc.constants));
}

ScopeStack prevScopeStack = (ScopeStack) scopeStack.clone();
try {
list = AVM2Graph.translateViaGraph(null, callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, thisHasDefaultToPrimitive);
} catch (SecondPassException spe) {
list = AVM2Graph.translateViaGraph(spe.getData(), callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, prevScopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, thisHasDefaultToPrimitive);
list = AVM2Graph.translateViaGraph(spe.getData(), callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, thisHasDefaultToPrimitive);
}
if (initTraits != null) {
loopi:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ protected boolean removeObfuscationGetSets(int classIndex, boolean isStatic, int
}

localData.scopeStack.clear();
localData.localScopeStack.clear();
localData.localRegs.clear();
localData.localRegAssignmentIps.clear();
localData.localRegs.clear();
Expand All @@ -109,6 +110,7 @@ protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool
localData.localRegs = new HashMap<>(body.max_regs);
localData.localRegAssignmentIps = new HashMap<>();
localData.scopeStack = new ScopeStack(true);
localData.localScopeStack = new ScopeStack(true);
List<MethodBody> callStack = new ArrayList<>();
callStack.add(body);
localData.callStack = callStack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scr
}

localData.scopeStack.clear();
localData.localScopeStack.clear();
localData.localRegs.clear();
localData.localRegAssignmentIps.clear();
localData.localRegs.clear();
Expand All @@ -202,6 +203,7 @@ protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool
localData.localRegs = new HashMap<>(body.max_regs);
localData.localRegAssignmentIps = new HashMap<>();
localData.scopeStack = new ScopeStack(true);
localData.localScopeStack = new ScopeStack(true);
List<MethodBody> callStack = new ArrayList<>();
callStack.add(body);
localData.callStack = callStack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ private static List<GraphException> getExceptionEntries(MethodBody body) {
return ret;
}

public AVM2Graph(AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, HashMap<Integer, Integer> localRegAssigmentIps) {
super(new AVM2GraphSource(code, isStatic, scriptIndex, classIndex, localRegs, scopeStack, abc, body, localRegNames, fullyQualifiedNames, localRegAssigmentIps), getExceptionEntries(body));
public AVM2Graph(AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, HashMap<Integer, Integer> localRegAssigmentIps) {
super(new AVM2GraphSource(code, isStatic, scriptIndex, classIndex, localRegs, abc, body, localRegNames, fullyQualifiedNames, localRegAssigmentIps), getExceptionEntries(body));
this.avm2code = code;
this.abc = abc;
this.body = body;
Expand Down Expand Up @@ -248,7 +248,8 @@ private void getIgnoredSwitches(AVM2LocalData localData, Set<GraphPart> allParts
TranslateStack finallyTryTargetStack = (TranslateStack) new TranslateStack("try_target");

AVM2LocalData localData2 = new AVM2LocalData(localData);
localData2.scopeStack = new ScopeStack();
//localData2.scopeStack = new ScopeStack();
localData2.localScopeStack = new ScopeStack();

List<GraphTargetItem> targetOutput;
try {
Expand Down Expand Up @@ -626,7 +627,8 @@ public Map<Integer, Set<Integer>> calculateLocalRegsUsage(List<ThrowState> throw
}

public static List<GraphTargetItem> translateViaGraph(SecondPassData secondPassData, List<MethodBody> callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, boolean thisHasDefaultToPrimitive) throws InterruptedException {
AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps);
ScopeStack localScopeStack = new ScopeStack();
AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localScopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps);

AVM2LocalData localData = new AVM2LocalData();
localData.secondPassData = secondPassData;
Expand All @@ -635,6 +637,7 @@ public static List<GraphTargetItem> translateViaGraph(SecondPassData secondPassD
localData.classIndex = classIndex;
localData.localRegs = localRegs;
localData.scopeStack = scopeStack;
localData.localScopeStack = localScopeStack;
localData.methodBody = body;
localData.callStack = callStack;
localData.abc = abc;
Expand Down Expand Up @@ -1063,7 +1066,8 @@ private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundG
st2.clear();
st2.add(new ExceptionAVM2Item(finallyException));
AVM2LocalData localData2 = new AVM2LocalData(localData);
localData2.scopeStack = new ScopeStack();
//localData2.scopeStack = new ScopeStack();
localData2.localScopeStack = new ScopeStack();

try {
//We are assuming Finally target has only 1 part
Expand Down Expand Up @@ -1181,7 +1185,8 @@ private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundG
}
}
AVM2LocalData localData2 = new AVM2LocalData(localData);
localData2.scopeStack = new ScopeStack();
//localData2.scopeStack = new ScopeStack();
localData2.localScopeStack = new ScopeStack();

List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
List<StopPartKind> stopPartKind2 = new ArrayList<>(stopPartKind);
Expand All @@ -1202,7 +1207,7 @@ private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundG
WithAVM2Item w = (WithAVM2Item) currentCatchCommands.get(0);
if (w.scope instanceof LocalRegAVM2Item) {
int regId = ((LocalRegAVM2Item) w.scope).regIndex;
for (GraphTargetItem item : localData.scopeStack) {
for (GraphTargetItem item : localData.localScopeStack) {
if (item instanceof WithObjectAVM2Item) {
WithObjectAVM2Item wo = (WithObjectAVM2Item) item;

Expand Down Expand Up @@ -2381,8 +2386,8 @@ public AVM2LocalData prepareBranchLocalData(BaseLocalData localData) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
AVM2LocalData ret = new AVM2LocalData(aLocalData);
ScopeStack copyScopeStack = new ScopeStack();
copyScopeStack.addAll(ret.scopeStack);
ret.scopeStack = copyScopeStack;
copyScopeStack.addAll(ret.localScopeStack);
ret.localScopeStack = copyScopeStack;
return ret;
}

Expand Down
Loading

0 comments on commit e9063e4

Please sign in to comment.