Issue #862 AS3 asm: do not read beyond return/throw instructions

This commit is contained in:
Jindra Petřík
2015-04-21 06:43:41 +02:00
parent 47b57eccf1
commit 2153612b46
5 changed files with 40 additions and 0 deletions
@@ -282,6 +282,7 @@ import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TranslateException;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.ExitItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.helpers.Helper;
@@ -297,6 +298,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -675,6 +677,7 @@ public class AVM2Code implements Cloneable {
public AVM2Code(ABCInputStream ais) throws IOException {
Map<Long, AVM2Instruction> codeMap = new TreeMap<>();
Map<Long, Long> endOffsets = new HashMap<>();
DumpInfo diParent = ais.dumpInfo;
List<Long> addresses = new ArrayList<>();
long startPos = ais.getPosition();
@@ -738,6 +741,11 @@ public class AVM2Code implements Cloneable {
}
codeMap.put(startOffset, new AVM2Instruction(startOffset, instr, actualOperands));
ais.endDumpLevel(instr.instructionCode);
long endOffset = ais.getPosition();
endOffsets.put(startOffset, endOffset);
if (instr.isExitInstruction()) { //do not continue if there is return/throw instruction
break;
}
} else {
ais.endDumpLevel();
break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions)
@@ -750,6 +758,18 @@ public class AVM2Code implements Cloneable {
}
}
//If there are gaps between instructions, fill them with Nops, so the jump offsets are correct
List<Long> starts = new ArrayList<>(new TreeSet<>(codeMap.keySet()));
for (int s = 0; s < starts.size() - 1/*last does not have next endoffset instruction*/; s++) {
long curEnd = endOffsets.get(starts.get(s));
if (!codeMap.containsKey(curEnd)) {
long nextStart = starts.get(s + 1);
for (long off = curEnd; off < nextStart; off++) {
codeMap.put(off, new AVM2Instruction(off, new NopIns(), new int[]{}));
}
}
}
code.addAll(codeMap.values());
}
@@ -169,4 +169,8 @@ public class InstructionDefinition implements Serializable {
}
return true;
}
public boolean isExitInstruction() {
return false;
}
}
@@ -45,4 +45,10 @@ public class ReturnValueIns extends InstructionDefinition {
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
@Override
public boolean isExitInstruction() {
return true;
}
}
@@ -40,4 +40,9 @@ public class ReturnVoidIns extends InstructionDefinition {
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
output.add(new ReturnVoidAVM2Item(ins));
}
@Override
public boolean isExitInstruction() {
return true;
}
}
@@ -45,4 +45,9 @@ public class ThrowIns extends InstructionDefinition {
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
@Override
public boolean isExitInstruction() {
return true;
}
}