Fixed AS3: try..catch in do..while vs do..while in try..catch

This commit is contained in:
Jindra Petřík
2021-02-06 08:42:52 +01:00
parent 3883a607db
commit 619ef52790
14 changed files with 375 additions and 6 deletions

View File

@@ -1086,6 +1086,45 @@ public class AVM2Graph extends Graph {
return false;
}
@Override
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops) {
Loop toBeLoop = null;
for (Loop el : loops) {
if ((el.loopContinue == part) && (el.phase == 0)) {
toBeLoop = el;
break;
}
}
if (toBeLoop == null) {
return true;
}
AVM2LocalData aLocalData = (AVM2LocalData) localData;
boolean inTry = false;
for (ABCException ex : body.exceptions) {
if (aLocalData.parsedExceptions.contains(ex)) {
continue;
}
int fixStart = avm2code.adr2pos(ex.start, true);
int fixEnd = avm2code.adr2pos(ex.end, true);
if (part.start == fixStart) {
inTry = true;
for (GraphPart be : toBeLoop.backEdges) {
if (be.start < fixStart || be.start >= fixEnd) {
//exists a backedge that is outside of try..catch
return true;
}
}
}
}
if (inTry) {
//it is in try and there's no backedge that's outside try
return false;
}
return true;
}
@Override
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
@@ -1338,7 +1377,7 @@ public class AVM2Graph extends Graph {
if (ft instanceof WithAVM2Item) {
pos++;
List<GraphTargetItem> withCommands = new ArrayList<>();
while (!(w.commands.get(pos) instanceof WithEndAVM2Item)) {
while (pos < w.commands.size() && !(w.commands.get(pos) instanceof WithEndAVM2Item)) {
withCommands.add(w.commands.get(pos));
pos++;
}

View File

@@ -1448,6 +1448,9 @@ public class Graph {
return false;
}
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops) {
return true;
}
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -1495,11 +1498,19 @@ public class Graph {
//List<GraphPart> loopContinues = getLoopsContinues(loops);
boolean isLoop = false;
Loop currentLoop = null;
boolean vCanHandleLoop = canHandleLoop(localData, part, loops);
Loop ignoredLoop = null;
for (Loop el : loops) {
if ((el.loopContinue == part) && (el.phase == 0)) {
currentLoop = el;
currentLoop.phase = 1;
isLoop = true;
if (vCanHandleLoop) {
currentLoop = el;
currentLoop.phase = 1;
isLoop = true;
} else {
ignoredLoop = el;
}
break;
}
}
@@ -1509,6 +1520,12 @@ public class Graph {
}
for (int l = loops.size() - 1; l >= 0; l--) {
Loop el = loops.get(l);
if (el == ignoredLoop) {
if (debugPrintGraph) {
System.err.println("ignoring to be loop " + el);
}
continue;
}
if (el == currentLoop) {
if (debugPrintGraph) {
System.err.println("ignoring current loop " + el);

View File

@@ -158,4 +158,46 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
+ "}\r\n",
false);
}
@Test
public void testTryDoWhile() {
decompileMethod("assembled", "testTryDoWhile", "trace(\"first\");\r\n"
+ "var _loc5_:* = rnd();\r\n"
+ "try\r\n"
+ "{\r\n"
+ "do\r\n"
+ "{\r\n"
+ "trace(\"second\");\r\n"
+ "}\r\n"
+ "while(_loc5_ <= 100);\r\n"
+ "\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "trace(\"in catch\");\r\n"
+ "}\r\n"
+ "trace(\"after\");\r\n",
false);
}
@Test
public void testTryDoWhile2() {
decompileMethod("assembled", "testTryDoWhile2", "trace(\"hello\");\r\n"
+ "var _loc5_:* = Math.random();\r\n"
+ "do\r\n"
+ "{\r\n"
+ "try\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "trace(\"in catch\");\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "while(_loc5_ <= 100);\r\n"
+ "trace(\"after\");\r\n",
false);
}
}

View File

@@ -17,5 +17,7 @@ program
#include "tests/TestSwitchDefault.script.asasm"
#include "tests/TestSwitch.script.asasm"
#include "tests/TestDeclareReg.script.asasm"
#include "tests/TestTryDoWhile.script.asasm"
#include "tests/TestTryDoWhile2.script.asasm"
; place to add next
end ; program

View File

@@ -0,0 +1,93 @@
class
refid "tests:TestTryDoWhile"
instance QName(PackageNamespace("tests"), "TestTryDoWhile")
extends QName(PackageNamespace(""), "Object")
flag SEALED
flag PROTECTEDNS
protectedns ProtectedNamespace("tests:TestTryDoWhile")
iinit
refid "tests:TestTryDoWhile/instance/init"
body
maxstack 1
localcount 1
initscopedepth 4
maxscopedepth 5
code
getlocal0
pushscope
getlocal0
constructsuper 0
returnvoid
end ; code
end ; body
end ; method
trait method QName(PackageNamespace(""), "run")
method
refid "tests:TestTryDoWhile/instance/run"
returns QName(PackageNamespace(""), "void")
body
maxstack 2
localcount 4
initscopedepth 4
maxscopedepth 5
code
getlocal0
pushscope
findproperty QName(PackageNamespace(""),"trace")
pushstring "first"
callpropvoid QName(PackageNamespace(""),"trace"), 1
findproperty QName(PackageNamespace(""),"rnd")
callproperty QName(PackageNamespace(""),"rnd"), 0
setlocal 5
ofs0010:
jump ofs0029
ofs0014:
label
findproperty QName(PackageNamespace(""),"trace")
pushstring "second"
callpropvoid QName(PackageNamespace(""),"trace"), 1
getlocal 5
pushbyte 100
ifngt ofs0029
jump ofs002d
ofs0029:
jump ofs0014
ofs002d:
jump ofs0035
ofs0031:
getlocal0
pushscope
setlocal 6
findproperty QName(PackageNamespace(""),"trace")
pushstring "in catch"
callpropvoid QName(PackageNamespace(""),"trace"), 1
ofs0035:
findproperty QName(PackageNamespace(""),"trace")
pushstring "after"
callpropvoid QName(PackageNamespace(""),"trace"), 1
returnvoid
end ; code
try from ofs0010 to ofs002d target ofs0031 type QName(PackageNamespace(""),"Error") name QName(PackageNamespace(""),"e") end
end ; body
end ; method
end ; trait
end ; instance
cinit
refid "tests:TestTryDoWhile/class/init"
body
maxstack 1
localcount 1
initscopedepth 3
maxscopedepth 4
code
getlocal0
pushscope
returnvoid
end ; code
end ; body
end ; method
end ; class

View File

@@ -0,0 +1,29 @@
script
sinit
refid "tests:TestTryDoWhile/init"
body
maxstack 2
localcount 1
initscopedepth 1
maxscopedepth 3
code
getlocal0
pushscope
findpropstrict Multiname("TestTryDoWhile", [PackageNamespace("tests")])
getlex QName(PackageNamespace(""), "Object")
pushscope
getlex Multiname("Object", [PrivateNamespace(null, "tests:TestTryDoWhile"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")])
newclass "tests:TestTryDoWhile"
popscope
initproperty QName(PackageNamespace("tests"), "TestTryDoWhile")
returnvoid
end ; code
end ; body
end ; method
trait class QName(PackageNamespace("tests"), "TestTryDoWhile")
#include "TestTryDoWhile.class.asasm"
end ; trait
end ; script

View File

@@ -0,0 +1,118 @@
class
refid "tests:TestTryDoWhile2"
instance QName(PackageNamespace("tests"), "TestTryDoWhile2")
extends QName(PackageNamespace(""), "Object")
flag SEALED
flag PROTECTEDNS
protectedns ProtectedNamespace("tests:TestTryDoWhile2")
iinit
refid "tests:TestTryDoWhile2/instance/init"
body
maxstack 1
localcount 1
initscopedepth 4
maxscopedepth 5
code
getlocal0
pushscope
getlocal0
constructsuper 0
returnvoid
end ; code
end ; body
end ; method
trait method QName(PackageNamespace(""), "run")
method
refid "tests:TestTryDoWhile2/instance/run"
returns QName(PackageNamespace(""), "void")
body
maxstack 2
localcount 4
initscopedepth 4
maxscopedepth 5
maxstack 3
localcount 3
initscopedepth 5
maxscopedepth 10
trait slot QName(PackageInternalNs("tests"),"_loc5_")
slotid 1
type null
end ; trait
code
getlocal0
pushscope
newactivation
dup
setlocal1
pushscope
findpropstrict QName(PackageNamespace(""),"trace")
pushstring "hello"
callproperty QName(PackageNamespace(""),"trace"), 1
pop
getscopeobject 1
findpropstrict QName(PackageNamespace(""),"Math")
getproperty QName(PackageNamespace(""),"Math")
callproperty QName(PackageNamespace(""),"random"), 0
coerce_a
setslot 1
xxx:
findpropstrict QName(PackageNamespace(""),"trace")
pushstring "second"
callproperty QName(PackageNamespace(""),"trace"), 1
pop
ofs0036:
jump ofs0056
ofs003c:
getlocal0
pushscope
getlocal1
pushscope
newcatch 0
dup
setlocal2
dup
pushscope
swap
setslot 1
findpropstrict QName(PackageNamespace(""),"trace")
pushstring "in catch"
callproperty QName(PackageNamespace(""),"trace"), 1
pop
popscope
kill 2
ofs0056:
getscopeobject 1
getslot 1
pushbyte 100
ifle xxx
findpropstrict QName(PackageNamespace(""),"trace")
pushstring "after"
callproperty QName(PackageNamespace(""),"trace"), 1
pop
returnvoid
end ; code
try from xxx to ofs0036 target ofs003c type QName(PackageNamespace(""),"Error") name QName(PackageNamespace(""),"e") end
end ; body
end ; method
end ; trait
end ; instance
cinit
refid "tests:TestTryDoWhile2/class/init"
body
maxstack 1
localcount 1
initscopedepth 3
maxscopedepth 4
code
getlocal0
pushscope
returnvoid
end ; code
end ; body
end ; method
end ; class

View File

@@ -0,0 +1,29 @@
script
sinit
refid "tests:TestTryDoWhile2/init"
body
maxstack 2
localcount 1
initscopedepth 1
maxscopedepth 3
code
getlocal0
pushscope
findpropstrict Multiname("TestTryDoWhile2", [PackageNamespace("tests")])
getlex QName(PackageNamespace(""), "Object")
pushscope
getlex Multiname("Object", [PrivateNamespace(null, "tests:TestTryDoWhile2"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")])
newclass "tests:TestTryDoWhile2"
popscope
initproperty QName(PackageNamespace("tests"), "TestTryDoWhile2")
returnvoid
end ; code
end ; body
end ; method
trait class QName(PackageNamespace("tests"), "TestTryDoWhile2")
#include "TestTryDoWhile2.class.asasm"
end ; trait
end ; script

View File

@@ -16,7 +16,7 @@
</define>
<define append="true">
<name>CONFIG::timeStamp</name>
<value>'05.02.2021'</value>
<value>'06.02.2021'</value>
</define>
<define append="true">
<name>CONFIG::air</name>

View File

@@ -16,7 +16,7 @@
</define>
<define append="true">
<name>CONFIG::timeStamp</name>
<value>'05.02.2021'</value>
<value>'06.02.2021'</value>
</define>
<define append="true">
<name>CONFIG::air</name>