If you are looking for the decompiler itself, visit https://github.com/jindrapetrik/jpexs-decompiler
NEW : We have got a new blog where we post some interesting SWF internals info.

#11 Zero jumps in finally blocks
Author:
googleCode

Date created:
Type: bug
Visibility: Everybody
Assigned to:
Labels: AS3DecompilationGoogle Code
State: closed 

Hi all. Yesterday i found another error with decompiling as3.
In some cases compiler puts "jump 0" instructions (inside body of lookupswitch)
in finally block implementation. Asdec does not recognize this and decompiled code looks
broken.
Here is the example code.
private function test1(param1:String):String{
var str:String=param1;
try
{
return str;
}
catch(e:Error)
{
trace("error is :"+e.message);
}
finally
{
return str;
}
}
Decompiled code
private function test1(param1:String) : String {
var param1:String;
var str:String;
param1=param1;
str=param1;
try
{
return str;
}
catch(e:Error)
{
trace("error is :"+e.message);
}
finally
{
return _loc5_;
}
}
P-code of finally block looks like this
...
ofs0071:getscopeobject 1
getslot 2
coerce_a
setlocal 5
pushbyte 2
jump ofs007e
ofs007e:label
pop
ofs0080:label
getlocal 5
kill 5
returnvalue
lookupswitch ofs0094 2 ofs0022 ofs0066 ofs0080
ofs0094:kill 5
...
When asdec examines the code it just passes jump 0 (jump ofs007e
ofs007e:label
) instruction and hence expression tree differs from original;
I made some fixes in AVM2Code.java. They're working for me. Don't know if that's right
way, but it can be useful
AVM2Code.java:
....
AVM2Instruction jmpIns =
code.get(adr2pos(fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = adr2pos(fixAddrAfterDebugLine(body.exceptions[e].end) +
jmpIns.getBytes().length + jmpIns.operands[0]);
finallyJumps.add(finStart);
if (unknownJumps.contains(finStart)) {
unknownJumps.remove((Integer) finStart);
}
for (int f = finStart; f <= end; f++) {
//change 1. inside finally block there can be zero jump instructions
//remember them
if (code.get(f).definition instanceof JumpIns){
int jumpPos = adr2pos(code.get(f).getOffsets().get(0));
finallyJumps.add(jumpPos);
if (unknownJumps.contains(jumpPos)) {
unknownJumps.remove((Integer) jumpPos);
}
}
//end of change 1.
if (code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = code.get(f);
if (swins.operands.length >= 3) {
if (swins.operands[0] == swins.getBytes().length) {
if (adr2pos(pos2adr(f) + swins.operands[2]) < finStart) {
finallyCommands = toSource(isStatic, classIndex, localRegs, stack,
scopeStack, abc, constants, method_info, body, finStart, f - 1).output;
returnPos = f + 1;
break;
}
}
}
}
}
break;
}
....
AVM2Instruction ins = code.get(ip);
//Ify s vice podminkama
if (ins.definition instanceof JumpIns) {
//change 2 sometimes zero jumps are needed
//original code:
/*if (ins.operands[0] == 0) {
ip++;
addr = pos2adr(ip);
} else if (ins.operands[0] > 0) {
int secondAddr = addr + ins.getBytes().length;
int jumpAddr = secondAddr + ins.operands[0];
int jumpPos = adr2pos(jumpAddr);//
*/
int secondAddr = addr + ins.getBytes().length;
int jumpAddr = secondAddr + ins.operands[0];
int jumpPos = adr2pos(jumpAddr);
if (ins.operands[0] == 0 && !finallyJumps.contains(jumpPos)) {
ip++;
addr = pos2adr(ip);
} else if (ins.operands[0] > 0 || finallyJumps.contains(jumpPos)) {
//end of change 2
if (finallyJumps.contains(jumpPos)) {
if (code.get(ip + 1).definition instanceof LabelIns) {
if (code.get(ip + 2).definition instanceof PopIns) {
if (code.get(ip + 3).definition instanceof LabelIns) {
.....
Hi, sorry for answering too late. I made some changes to the code and now Asdec version
1.0.0 is available. The finally block problem should be fixed.
State: →closed
Title: Zero jumps in finally blocks→Zero jumps in finally blocks
Type: →bug
Visibility: →Everybody
Title: Zero jumps in finally blocks→Zero jumps in finally blocks
Type: →bug
Visibility: →Everybody