JPEXS Free Flash Decompiler Issue Tracker

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 issuesList of issues

#22 dup, setlocal issue
Date created:
Type: bug
Visibility: Everybody
Assigned to:
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="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);
admin
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;
user
State: →closed
Title: dup, setlocal issue→dup, setlocal issue
Type: →bug
Visibility: →Everybody