/* * Copyright (C) 2010-2011 JPEXS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.jpexs.asdec.abc.avm2.flowgraph; import com.jpexs.asdec.abc.avm2.AVM2Code; import com.jpexs.asdec.abc.avm2.ConvertException; import com.jpexs.asdec.abc.avm2.instructions.IfTypeIns; import com.jpexs.asdec.abc.avm2.instructions.jumps.IfFalseIns; import com.jpexs.asdec.abc.avm2.instructions.jumps.IfTrueIns; import com.jpexs.asdec.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.asdec.abc.avm2.instructions.localregs.GetLocalTypeIns; import com.jpexs.asdec.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.asdec.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.asdec.abc.avm2.instructions.other.ReturnVoidIns; import com.jpexs.asdec.abc.avm2.instructions.stack.DupIns; import com.jpexs.asdec.abc.avm2.instructions.stack.PopIns; import com.jpexs.asdec.abc.avm2.instructions.stack.PushFalseIns; import com.jpexs.asdec.abc.avm2.instructions.stack.PushTrueIns; import com.jpexs.asdec.abc.avm2.instructions.stack.SwapIns; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author JPEXS */ public class Graph { public GraphPart head; public List ignored = new ArrayList(); private int trueReg = -1; private int falseReg = -1; public Graph(AVM2Code code) { int start = checkSWFSecureStart(code); head=makeGraph(new Stack(), code, start, new ArrayList()); } private int checkSWFSecureStart(AVM2Code code) { if (code.code.size() < 2) { return 0; } if (!((code.code.get(0).definition instanceof PushFalseIns) || (code.code.get(0).definition instanceof PushTrueIns))) { return 0; } if (!((code.code.get(1).definition instanceof PushFalseIns) || (code.code.get(1).definition instanceof PushTrueIns))) { return 0; } int pos = 2; Stack myStack = new Stack(); int ip = 0; int setCount = 0; while (ip < code.code.size()) { if (code.code.get(ip).definition instanceof PushFalseIns) { myStack.push(Boolean.FALSE); } else if (code.code.get(ip).definition instanceof PushTrueIns) { myStack.push(Boolean.TRUE); } else if (code.code.get(ip).definition instanceof SwapIns) { Boolean b1 = myStack.pop(); Boolean b2 = myStack.pop(); myStack.push(b1); myStack.push(b2); } else if (code.code.get(ip).definition instanceof JumpIns) { try { ip = code.adr2pos(code.pos2adr(ip + 1) + code.code.get(ip).operands[0]); } catch (ConvertException ex) { Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, null, ex); } continue; } else if (code.code.get(ip).definition instanceof SetLocalTypeIns) { Boolean val = myStack.pop(); if (val == true) { trueReg = ((SetLocalTypeIns) code.code.get(ip).definition).getRegisterId(code.code.get(ip)); } else { falseReg = ((SetLocalTypeIns) code.code.get(ip).definition).getRegisterId(code.code.get(ip)); } setCount++; if (setCount == 2) { return ip + 1; } } ip++; } return 0; } private GraphPart makeGraph(Stack myStack,AVM2Code code, int start, List allBlocks) { GraphPart ret=new GraphPart(start,-1); ret.instanceCount=1; allBlocks.add(ret); GraphPart actual=ret; try { int ip = start; while (ip < code.code.size()) { for (GraphPart block : allBlocks) { if (block.containsIP(ip)) { if(block.start= 2) { Boolean b1 = myStack.pop(); Boolean b2 = myStack.pop(); myStack.push(b1); myStack.push(b2); ignored.add(ip); } } else if (code.code.get(ip).definition instanceof DupIns) { if (!myStack.empty()) { Boolean b = myStack.pop(); myStack.push(b); myStack.push(b); ignored.add(ip); } } else if ((code.code.get(ip).definition instanceof JumpIns) || forceJump) { int jumpIp = code.adr2pos(code.pos2adr(ip + 1) + code.code.get(ip).operands[0]); actual.end=ip; GraphPart newActual=makeGraph(myStack,code,jumpIp,allBlocks); actual.nextParts.add(newActual); return ret; } else if (code.code.get(ip).definition instanceof IfTypeIns) { if (forceSkip) { ip++; continue; } actual.end=ip; int jumpIp = code.adr2pos(code.pos2adr(ip + 1) + code.code.get(ip).operands[0]); GraphPart onTrue=makeGraph(myStack,code, jumpIp, allBlocks); actual.nextParts.add(onTrue); GraphPart onFalse=makeGraph(myStack,code, ip + 1, allBlocks); actual.nextParts.add(onFalse); return ret; } else if ((code.code.get(ip).definition instanceof ReturnValueIns) || (code.code.get(ip).definition instanceof ReturnVoidIns)) { ip++; break; } ip++; } actual.end=ip-1; return ret; } catch (ConvertException ex) { Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, null, ex); } return null; } }