JPEXS Free Flash Decompiler Issue Tracker

If you are looking for the decompiler itself, visit

+ update 2020: WARNING - support of the decompiler is now VERY LIMITED. There are no active developers. This means we will NOT develop new features and/or fix most of bugs. We left the tracker running in case somebody from community would like to work on it. Sorry for the inconvenience.

List of issuesList of issues

#22 dup, setlocal issue
Date created:
Type: bug
Visibility: Everybody
Assigned to:
Labels: AS3DecompilationGoogle Code
State: closed Help

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=""; xmlns:s="library://" xmlns:mx="library://"> <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]""; 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. // 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