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.
List of issues#22 dup, setlocal issue
Author: googleCode
Date created:
Type: bug
Visibility: Everybody
Assigned to:
Labels: AS3DecompilationGoogle Code
State: closed
Hi. I found that code with 'dup' instructions sometimes is decompiled wrong.
To reproduce the problem you can create simpliest flex application with label component
and compile it with merging framework code into swf.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:Label/>
</s:Application>
After compiling, open method 'truncateText' of spark.components.Label class.
There are these lines for example
//line 50:
getlocal_0
getlocal_2
getlocal 4
callproperty m[1844]"-.computeLastAllowedLineIndex" 2
convert_i
dup
setlocal 6
pushbyte 1
add
getlex m[1796]"http://www.adobe.com/2006/flex/mx/internal.textLines"
getproperty m[3233]"length"
ifnlt ofs0070
inclocal_i 6
pushtrue
setlocal 7
Here is how these lines are decompiled
_loc6_=this.computeLastAllowedLineIndex(param2,_loc4_);
if((this.computeLastAllowedLineIndex(param2,_loc4_))+1<textLines.length)
{
_loc6_++;
_loc7_=true;
}
The right code is
_loc6_=this.computeLastAllowedLineIndex(param2,_loc4_);
if(_loc6_+1<textLines.length)
{
_loc6_++;
_loc7_=true;
}
That happens after asdec decompiled "dup .. setlocal " instruction sequence.
When asdec steps to 'add' instruction, it takes previous TreeItem from stack, which is
call of 'computeLastAllowedLineIndex'.
To avoid this duplicate we might to remember local variable, that we set during
'setlocal'. So hard to translate to english, sorry.
Anyway, i created followed patch. It works for me.
//AVM2Code.java line 1478
} else if (insAfter.definition instanceof SetLocalTypeIns) {
//chained assignments
int reg = (((SetLocalTypeIns) insAfter.definition).getRegisterId(insAfter));
for (int t = ip + 1; t < end - 1; t++) {
if (code.get(t).definition instanceof GetLocalTypeIns) {
if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg)
{
if (code.get(t + 1).definition instanceof KillIns) {
if (code.get(t + 1).operands[0] == reg) {
ConvertOutput assignment = toSource(isStatic, classIndex, localRegs, stack, scopeStack,
abc, constants, method_info, body, ip + 2, t - 1, localRegNames);
stack.push(assignment.output.remove(assignment.output.size() - 1));
ip = t + 2;
continue iploop;
}
}
}
}
}
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants,
ins, method_info, output, body, abc, localRegNames);
//In case of 'dup ... setlocal' we need to remember local variable,
//whose value we just set
//or previous TreeItem will be duplicated in code listing
TreeItem v = (TreeItem) stack.pop();
stack.push(new LocalRegTreeItem(ins, reg, localRegs.get(reg)));
stack.push(v);
//end of change
ip++;
addr = pos2adr(ip);
Hi, thank you for reporting.
You're right, it needs to be fixed, but it is not so easy.
The change you suggests breaks a few things like property pre/post increments.
I made the final correction and pushed this code to the repository:
if (!isKilled(reg, ip, end)) {
TreeItem v = (TreeItem) stack.pop();
stack.push(new LocalRegTreeItem(ins, reg, v));
stack.push(v);
} else {
ins.definition.translate(isStatic, classIndex, localRegs, stack,
scopeStack, constants, ins, method_info, output, body, abc, localRegNames);
}
ip++;
addr = pos2adr(ip);
break;
State: →closed
Title: dup, setlocal issue→dup, setlocal issue
Type: →bug
Visibility: →Everybody
Title: dup, setlocal issue→dup, setlocal issue
Type: →bug
Visibility: →Everybody