mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-23 08:25:33 +00:00
Fixed: AS decompilation - §§push before loop
This commit is contained in:
@@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
|
||||
- Rename invalid identifiers renames identifiers with a dollar sign
|
||||
- [#1676] Messages on movie tags when Flash Player ActiveX not available
|
||||
- [#1677] DefineFont2/3 - missing codeTableOffset if numGlyphs is zero and font has layout
|
||||
- AS decompilation - §§push before loop
|
||||
|
||||
## [14.3.1] - 2021-03-25
|
||||
### Fixed
|
||||
|
||||
@@ -1611,7 +1611,7 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
|
||||
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates, TranslateStack stack) {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
if (loopItem instanceof WhileItem) {
|
||||
WhileItem w = (WhileItem) loopItem;
|
||||
@@ -1620,6 +1620,22 @@ public class AVM2Graph extends Graph {
|
||||
HasNextAVM2Item hn = (HasNextAVM2Item) w.expression.get(w.expression.size() - 1);
|
||||
if (hn.obj != null) {
|
||||
if (hn.obj.getNotCoerced().getThroughRegister().getNotCoerced() instanceof FilteredCheckAVM2Item) {
|
||||
|
||||
//All items are moved from stack to output before entering while,
|
||||
// this code block moves them back to stack
|
||||
int pushnum = 0;
|
||||
for (int i = output.size() - 2 /*last is loop*/; i >= 0; i--) {
|
||||
if (output.get(i) instanceof PushItem) {
|
||||
pushnum++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int rem = output.size() - 1 - pushnum;
|
||||
for (int i = output.size() - 1 - pushnum; i <= output.size() - 2; i++) {
|
||||
stack.push(((PushItem) output.remove(rem)).value);
|
||||
}
|
||||
//---------- end moving back to stack
|
||||
if (w.commands.size() >= 3) {
|
||||
int pos = 0;
|
||||
Set<Integer> localRegsToKill = new HashSet<>();
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.jpexs.decompiler.graph.GraphSourceItemPos;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
import com.jpexs.decompiler.graph.model.BranchStackResistant;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.util.ArrayList;
|
||||
@@ -48,7 +49,7 @@ import java.util.Set;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class FunctionActionItem extends ActionItem {
|
||||
public class FunctionActionItem extends ActionItem implements BranchStackResistant {
|
||||
|
||||
public List<GraphTargetItem> actions;
|
||||
|
||||
|
||||
@@ -1350,7 +1350,7 @@ public class Graph {
|
||||
return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, stopPartKind, loops, throwStates, null, staticOperation, path, 0);
|
||||
}
|
||||
|
||||
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
|
||||
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates, TranslateStack stack) {
|
||||
return loopItem;
|
||||
}
|
||||
|
||||
@@ -1901,6 +1901,9 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoop) {
|
||||
makeAllCommands(ret, stack);
|
||||
}
|
||||
if (debugPrintGraph) {
|
||||
System.err.println("loopsize:" + loops.size());
|
||||
}
|
||||
@@ -2675,7 +2678,7 @@ public class Graph {
|
||||
}
|
||||
currentLoop.phase = 2;
|
||||
|
||||
GraphTargetItem replaced = checkLoop(ret, li, localData, loops, throwStates);
|
||||
GraphTargetItem replaced = checkLoop(ret, li, localData, loops, throwStates, sPreLoop);
|
||||
if (replaced != li) {
|
||||
int index = ret.indexOf(li);
|
||||
ret.remove(index);
|
||||
@@ -2951,21 +2954,18 @@ public class Graph {
|
||||
clen--;
|
||||
}
|
||||
}
|
||||
while (stack.size() > 0) {
|
||||
GraphTargetItem p = stack.pop();
|
||||
for (int i = stack.size() - 1; i >= 0; i--) {
|
||||
GraphTargetItem p = stack.get(i);
|
||||
if (p instanceof BranchStackResistant) {
|
||||
continue;
|
||||
}
|
||||
stack.remove(i);
|
||||
if (!(p instanceof PopItem)) {
|
||||
if (p instanceof FunctionActionItem) {
|
||||
if (isExit) {
|
||||
//ASC2 leaves some function calls unpopped on stack before returning from a method
|
||||
commands.add(clen, p);
|
||||
} else {
|
||||
if (isExit) {
|
||||
//ASC2 leaves some function calls unpopped on stack before returning from a method
|
||||
commands.add(clen, p);
|
||||
} else {
|
||||
commands.add(clen, new PushItem(p));
|
||||
}
|
||||
commands.add(clen, new PushItem(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,22 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPushWhile() {
|
||||
decompileMethod("assembled", "testPushWhile", "var _loc3_:int = 5;\r\n"
|
||||
+ "§§push(obfuscated[\"xxx\"] = new [\"ByteArray\"]());\r\n"
|
||||
+ "§§push(50);\r\n"
|
||||
+ "while(§§dup(§§pop()))\r\n"
|
||||
+ "{\r\n"
|
||||
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 41 ^ 111;\r\n"
|
||||
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 84;\r\n"
|
||||
+ "§§push(§§pop() - 1);\r\n"
|
||||
+ "}\r\n"
|
||||
+ "§§pop();\r\n"
|
||||
+ "§§pop();\r\n",
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSlotDup() {
|
||||
decompileMethod("assembled", "testSetSlotDup", "var _loc5_:int = 5;\r\n"
|
||||
|
||||
Binary file not shown.
@@ -28,5 +28,6 @@ program
|
||||
#include "tests/TestDecrementPrecedence.script.asasm"
|
||||
#include "tests/TestSwitchGoto.script.asasm"
|
||||
#include "tests/TestTryWhile.script.asasm"
|
||||
#include "tests/TestPushWhile.script.asasm"
|
||||
; place to add next
|
||||
end ; program
|
||||
|
||||
99
libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushWhile.class.asasm
vendored
Normal file
99
libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushWhile.class.asasm
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
class
|
||||
refid "tests:TestPushWhile"
|
||||
instance QName(PackageNamespace("tests"), "TestPushWhile")
|
||||
extends QName(PackageNamespace(""), "Object")
|
||||
flag SEALED
|
||||
flag PROTECTEDNS
|
||||
protectedns ProtectedNamespace("tests:TestPushWhile")
|
||||
iinit
|
||||
refid "tests:TestPushWhile/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:TestPushWhile/instance/run"
|
||||
returns QName(PackageNamespace(""), "void")
|
||||
body
|
||||
maxstack 2
|
||||
localcount 4
|
||||
initscopedepth 4
|
||||
maxscopedepth 5
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
pushbyte 5
|
||||
setlocal 3
|
||||
|
||||
pushstring "ByteArray"
|
||||
dup
|
||||
findpropstrict MultinameL([PackageNamespace("flash.utils","1")])
|
||||
swap
|
||||
constructprop MultinameL([PackageNamespace("flash.utils","1")]), 0
|
||||
dup
|
||||
getlex QName(PackageNamespace("","2"),"obfuscated")
|
||||
swap
|
||||
pushstring "xxx"
|
||||
swap
|
||||
setproperty MultinameL([PackageNamespace("","2")])
|
||||
pushint 50
|
||||
ofs0016:
|
||||
label
|
||||
dup
|
||||
iffalse ofs0039
|
||||
decrement_i
|
||||
swap
|
||||
dup
|
||||
dup
|
||||
getproperty QName(PackageNamespace("","2"),"length")
|
||||
pushbyte 41
|
||||
pushbyte 111
|
||||
bitxor
|
||||
setproperty MultinameL([PackageNamespace("","2")])
|
||||
dup
|
||||
dup
|
||||
getproperty QName(PackageNamespace("","2"),"length")
|
||||
pushbyte 9
|
||||
pushbyte 84
|
||||
bitxor
|
||||
setproperty MultinameL([PackageNamespace("","2")])
|
||||
swap
|
||||
jump ofs0016
|
||||
ofs0039:
|
||||
pop
|
||||
pop
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
end ; trait
|
||||
end ; instance
|
||||
cinit
|
||||
refid "tests:TestPushWhile/class/init"
|
||||
body
|
||||
maxstack 1
|
||||
localcount 1
|
||||
initscopedepth 3
|
||||
maxscopedepth 4
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
end ; class
|
||||
29
libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushWhile.script.asasm
vendored
Normal file
29
libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushWhile.script.asasm
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
script
|
||||
sinit
|
||||
refid "tests:TestPushWhile/init"
|
||||
body
|
||||
maxstack 2
|
||||
localcount 1
|
||||
initscopedepth 1
|
||||
maxscopedepth 3
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
|
||||
findpropstrict Multiname("TestPushWhile", [PackageNamespace("tests")])
|
||||
getlex QName(PackageNamespace(""), "Object")
|
||||
pushscope
|
||||
|
||||
getlex Multiname("Object", [PrivateNamespace(null, "tests:TestPushWhile"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")])
|
||||
newclass "tests:TestPushWhile"
|
||||
popscope
|
||||
initproperty QName(PackageNamespace("tests"), "TestPushWhile")
|
||||
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
trait class QName(PackageNamespace("tests"), "TestPushWhile")
|
||||
#include "TestPushWhile.class.asasm"
|
||||
end ; trait
|
||||
end ; script
|
||||
Binary file not shown.
Reference in New Issue
Block a user