├── PhpIL ├── __init__.py ├── variable.py ├── codeEmitter.py ├── typesData.py ├── opcodes.py ├── settings.py ├── probability.py ├── program.py ├── instructions.py ├── code_generators.py ├── program_builder.py ├── operation.py ├── lifter.py └── analyzer.py ├── coverage ├── phpcov.so ├── setup.py └── phpcov.c ├── main.py └── README.md /PhpIL/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /coverage/phpcov.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teambi0s/phpil/HEAD/coverage/phpcov.so -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from PhpIL import program_builder 2 | from PhpIL import program 3 | from PhpIL import lifter 4 | 5 | def main(): 6 | pb = program_builder.ProgramBuilder() 7 | for i in range(4): 8 | pb.generateRandomInst() 9 | 10 | prog = pb.finish() 11 | 12 | lift = lifter.Lifter(prog) 13 | lift.doLifting() 14 | code = lift.getCode() 15 | print code 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /PhpIL/variable.py: -------------------------------------------------------------------------------- 1 | class Variable: 2 | 3 | def __init__(self,id): 4 | self.id = id 5 | 6 | def __eq__(self, other): 7 | if not isinstance(other, Variable): 8 | return False 9 | if self.id == other.id: 10 | return True 11 | return False 12 | 13 | def __str__(self): 14 | return "$v"+str(self.id) 15 | 16 | def __hash__(self): 17 | # print "AA" 18 | return hash(self.id) 19 | 20 | def __repr__(self): 21 | return "v"+str(self.id) 22 | 23 | if __name__ == '__main__': 24 | print Variable(1) 25 | -------------------------------------------------------------------------------- /PhpIL/codeEmitter.py: -------------------------------------------------------------------------------- 1 | class CodeEmitter: 2 | 3 | def __init__(self): 4 | self.code = "" 5 | self.indentLevel = 0 6 | 7 | def emit(self, text): 8 | self.code += " "*self.indentLevel + text + "\n" 9 | 10 | def emitline(self, line): 11 | self.emit(line + ";") 12 | 13 | def increaseIndentLevel(self): 14 | self.indentLevel += 1 15 | 16 | def decreaseIndentLevel(self): 17 | self.indentLevel -= 1 18 | 19 | def getCode(self): 20 | return "" 21 | 22 | def __str__(self): 23 | return self.getCode() 24 | -------------------------------------------------------------------------------- /coverage/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | 3 | module1 = Extension('phpcov', 4 | define_macros = [('MAJOR_VERSION', '1'), 5 | ('MINOR_VERSION', '0')], 6 | include_dirs = ['/usr/local/include'], 7 | # libraries = ['tcl83'], 8 | library_dirs = ['/usr/local/lib'], 9 | sources = ['./phpcov.c']) 10 | 11 | setup (name = 'phpcov', 12 | version = '1.0', 13 | description = 'Package to obtain code coverage', 14 | author = 'Vignesh S Rao', 15 | author_email = 'vigneshsrao5@gmail.com', 16 | url = 'https://docs.python.org/extending/building', 17 | long_description = ''' 18 | This is really just a demo package. 19 | ''', 20 | ext_modules = [module1]) 21 | -------------------------------------------------------------------------------- /PhpIL/typesData.py: -------------------------------------------------------------------------------- 1 | 2 | class Types: 3 | 4 | Null = 0 5 | Integer = 1 << 0 6 | Float = 1 << 1 7 | String = 1 << 2 8 | Boolean = 1 << 3 9 | Object = 1 << 4 10 | Function = 1 << 5 | String 11 | Class = 1 << 6 12 | Array = 1 << 7 13 | Unknown = 1 << 8 14 | 15 | 16 | class FunctionSignature: 17 | 18 | def __init__(self, numArgs, outerVars): 19 | self.numArgs = numArgs 20 | self.inputTypes = [Types.Unknown for i in range(numArgs)] 21 | self.returnType = Types.Unknown 22 | self.outerVars = outerVars 23 | self.isCons = True 24 | 25 | def setReturnType(self, type): 26 | self.returnType = type 27 | 28 | def getReturnType(self): 29 | return self.returnType 30 | 31 | def getOuterVars(self): 32 | return self.outerVars 33 | 34 | def setInputTypes(self, types): 35 | for i, type in enumerate(types): 36 | self.inputTypes[i] = type 37 | 38 | def getInputTypes(self): 39 | return self.inputTypes 40 | 41 | def getNumArgs(self): 42 | return self.numArgs 43 | 44 | def isConstructing(self): 45 | return self.isCons 46 | -------------------------------------------------------------------------------- /PhpIL/opcodes.py: -------------------------------------------------------------------------------- 1 | class opcodes: 2 | 3 | opcodeList = [ "Nop", "LoadInteger", "LoadFloat", "LoadString", "LoadBoolean", "LoadNull", "CreateObject", "CreateArray", "CallFunction", "Print", "BeginFunction", "EndFunction", "BeginIf", "BeginElse", "EndIf", "BeginWhile", "EndWhile", "BeginFor", "EndFor", "BeginForEach", "EndForEach", "Return", "Break", "Continue", "BeginTry", "BeginCatch", "EndTryCatch", "BeginClass", "EndClass", "UnaryOperation", "BinaryOperation", "Include", "Eval", "Phi", "Copy", "BeginDoWhile", "EndDoWhile", "ThrowException","CreateDict","GetArrayElem","GetArrayElem"] 4 | 5 | Nop, \ 6 | LoadInteger, \ 7 | LoadFloat, \ 8 | LoadString, \ 9 | LoadBoolean, \ 10 | LoadNull, \ 11 | CreateObject, \ 12 | CreateArray, \ 13 | CallFunction, \ 14 | Print, \ 15 | BeginFunction, \ 16 | EndFunction, \ 17 | BeginIf, \ 18 | BeginElse, \ 19 | EndIf, \ 20 | BeginWhile, \ 21 | EndWhile, \ 22 | BeginFor, \ 23 | EndFor, \ 24 | BeginForEach, \ 25 | EndForEach, \ 26 | Return, \ 27 | Break, \ 28 | Continue, \ 29 | BeginTry, \ 30 | BeginCatch, \ 31 | EndTryCatch, \ 32 | BeginClass, \ 33 | EndClass, \ 34 | UnaryOperation, \ 35 | BinaryOperation, \ 36 | Include, \ 37 | Eval, \ 38 | Phi, \ 39 | Copy, \ 40 | BeginDoWhile, \ 41 | EndDoWhile, \ 42 | ThrowException, \ 43 | CreateDict, \ 44 | GetArrayElem, \ 45 | SetArrayElem = range(len(opcodeList)) 46 | 47 | 48 | 49 | if __name__ == '__main__': 50 | print opcodes.Nop 51 | -------------------------------------------------------------------------------- /PhpIL/settings.py: -------------------------------------------------------------------------------- 1 | import code_generators 2 | 3 | class Settings: 4 | 5 | allCodeGenerators = { 6 | code_generators.CodeGenerator.integerLiteralGenerator : 5, 7 | code_generators.CodeGenerator.floatLiteralGenerator : 2, 8 | code_generators.CodeGenerator.stringLiteralGenerator : 3, 9 | code_generators.CodeGenerator.booleanLiteralGenerator : 2, 10 | code_generators.CodeGenerator.nullValueGenerator : 2, 11 | code_generators.CodeGenerator.unaryOperationGenerator : 20, 12 | code_generators.CodeGenerator.binaryOperationGenerator : 20, 13 | code_generators.CodeGenerator.phiGenerator : 0, 14 | code_generators.CodeGenerator.whileLoopGenerator : 5, 15 | code_generators.CodeGenerator.ifStatementGenerator : 20, 16 | code_generators.CodeGenerator.forLoopGenerator : 15, 17 | code_generators.CodeGenerator.breakGenerator : 20, 18 | code_generators.CodeGenerator.continueGenerator : 20, 19 | code_generators.CodeGenerator.functionDefinationGenerator : 30, 20 | code_generators.CodeGenerator.functionReturnGenerator : 0, 21 | code_generators.CodeGenerator.functionCallGenerator : 80, 22 | code_generators.CodeGenerator.tryCatchGenerator : 1, 23 | code_generators.CodeGenerator.throwGenerator : 0, 24 | code_generators.CodeGenerator.floatArrayGenerator : 20, 25 | code_generators.CodeGenerator.intArrayGenerator : 20, 26 | code_generators.CodeGenerator.arrayLiteralGenerator : 20, 27 | code_generators.CodeGenerator.doWhileLoopGenerator : 5, 28 | code_generators.CodeGenerator.dictGenerator: 10, 29 | code_generators.CodeGenerator.getArrayElemGenerator: 20, 30 | code_generators.CodeGenerator.setArrayElemGenerator: 20 31 | } 32 | -------------------------------------------------------------------------------- /coverage/phpcov.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define SHM_SIZE 0x1000 15 | #define SHM_KEY 0x1234 16 | 17 | typedef struct covdata{ 18 | char* snapshot; 19 | char* shmem; 20 | } covdata; 21 | 22 | covdata* cdata; 23 | PyObject *init(); 24 | PyObject *evalCoverage(); 25 | 26 | PyObject *init(PyObject *self) 27 | { 28 | int shmid = shmget(SHM_KEY, SHM_SIZE, 0644|IPC_CREAT); 29 | char* shmem = shmat(shmid, NULL, 0); 30 | memset(shmem,0,SHM_SIZE); 31 | cdata = (covdata*)malloc(sizeof(covdata)); 32 | cdata->shmem = shmem; 33 | cdata->snapshot = (char*)malloc(SHM_SIZE); 34 | memset(cdata->snapshot,0,SHM_SIZE); 35 | Py_INCREF(Py_None); 36 | return Py_None; 37 | } 38 | 39 | PyObject *evalCoverage(PyObject *self) 40 | { 41 | int newPathFound=0; 42 | for (int i=0; ishmem[i]; 45 | uint8_t oldVal = cdata->snapshot[i]; 46 | for (int j=0; j<8; j++) 47 | { 48 | if ((val & (1<snapshot[i]=oldVal; 53 | } 54 | } 55 | } 56 | 57 | return Py_BuildValue("i", newPathFound); 58 | } 59 | 60 | PyObject *getpoints(PyObject *self) 61 | { 62 | char *points = (char*)calloc(1,((SHM_SIZE*3)+1)); 63 | char temp[10]={0}; 64 | for (int i=0; ishmem[i]); 67 | strcat(points, temp); 68 | } 69 | return Py_BuildValue("s",points); 70 | } 71 | 72 | static PyMethodDef phpcovMethods[] = { 73 | {"evalCoverage", evalCoverage, METH_VARARGS, "Execute a shell command."}, 74 | {"init", init, METH_VARARGS, "Execute a shell command."}, 75 | {"getpoints", getpoints, METH_VARARGS, "Execute a shell command."}, 76 | {NULL, NULL, 0, NULL} /* Sentinel */ 77 | }; 78 | 79 | PyMODINIT_FUNC initphpcov(void) 80 | { 81 | (void) Py_InitModule("phpcov", phpcovMethods); 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # phpil 2 | 3 | A Fuzzer for the PHP language. The core concept is based on 4 | [Fuzzili](https://github.com/googleprojectzero/fuzzilli). Basically, its a port 5 | of Fuzzili, re-written in python for PHP :). 6 | 7 | Currently only code generation is present. A python module for collecting 8 | clang’s sanitizer-coverage is present in [coverage](/coverage). 9 | 10 | We did this as a course project for the college, but the course got completed 11 | before we completed the entire fuzzer :). So it currently its a random php 12 | program generator. Might work more on this if we find time later. 13 | 14 | To run simply do 15 | 16 | ``` sh 17 | python main.py 18 | ``` 19 | 20 | That will print out a syntactically and semantically correct PHP code sample. 21 | 22 | 23 | ## How it works 24 | 25 | It works in a similar manner as Fuzzili. The fuzzing is done on a IR (PHPIL). A 26 | lifter lifts the PhpIL code to the PHP code when all the processing for the 27 | sample is done. The intermediate language (PHPIL) has opcodes which should on a 28 | high level cover most of the PHP functionalities (we did not do it for all the 29 | functionalities yet). Here is a high level overview of the working - 30 | 31 | - [Code Generators](/PhpIL/code_generators.py) - The code generators use the 32 | opcodes to generate blocks of semantically and syntactically correct code. This 33 | code is still in PhpIL. Once a block of code is generated, it is passed on to 34 | the analyzers for further analysis. 35 | 36 | - [Analyzers](/PhpIL/analyzer.py) - Currently supports 3 types of analysis - 37 | - Scope Analyzer - keeps track of the scope of each of the 38 | variables that is currently in use. 39 | - Context Analyzer - This is used to keep track of the program context. For 40 | example, we don’t want to emit a ‘return‘ instruction when we 41 | are not even within a function. 42 | - Type Analyzer - Its used to infer the types of the variables used 43 | in the input program. 44 | 45 | - [lifter](/PhpIL/lifter.py) - Finally we need to convert the PHPIL code to PHP 46 | code. This job is taken care of by the lifter. 47 | 48 | ## Other notes 49 | 50 | * Coverage - We can use clang sanitizer coverage to track the code coverage 51 | dynamically. For this we just need to compile php with the right options. 52 | [phpcov.c](coverage/phpcov.c) is a python module to track the code coverage in 53 | python. This is very similar to Fuzzili. We use a shared memory region to 54 | share the coverage data between the fuzzer and the binary. It has not been 55 | integrated yet though. 56 | 57 | * [program_builder](PhpIL/program_builder.py) - used to keep track of the 58 | current program that is being built/modified. Basically, its an instance of a 59 | PhpIL program. 60 | 61 | * [settings](PhpIL/settings.py) - Governs the probability of a code generator 62 | being selected. The higher the value of a code generator, the more likely it 63 | is to appear in the sample. If zero, it will never appear. 64 | 65 | ## TODOs 66 | 67 | Of course there are many things left. To name a few - 68 | * Mutation 69 | * Coverage 70 | * Sane selection of integers/strings 71 | * Execution and crash tracking 72 | 73 | ## Authors 74 | 75 | * [Vignesh Rao](https://twitter.com/sherl0ck__) 76 | * [Tarunkant Gupta](https://twitter.com/TarunkantG) 77 | * [Saastha Vasan](https://twitter.com/ThinkMalicious) 78 | 79 | -------------------------------------------------------------------------------- /PhpIL/probability.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | 4 | class Random: 5 | 6 | '''Returns True if the probability is achieved and False otherwise''' 7 | @staticmethod 8 | def probability(prob): 9 | if prob == 1: 10 | return True 11 | if random.uniform(0,1) < prob: 12 | return True 13 | return False 14 | 15 | '''if probability is true then call funcs[0] else call funcs[1]''' 16 | @staticmethod 17 | def withprobability(prob, *funcs): 18 | onTrue = funcs[0] 19 | onFalse = None 20 | if len(funcs) == 2: 21 | onFalse = funcs[1] 22 | 23 | if Random.probability(prob): 24 | return onTrue() 25 | elif onFalse is not None: 26 | return onFalse() 27 | 28 | '''select and execute a function from list of functions, with equal probability''' 29 | @staticmethod 30 | def withEqualProbability(*funcs): 31 | selected = Random.chooseUniform(funcs) 32 | return selected() 33 | 34 | '''select a list element with equal probability''' 35 | @staticmethod 36 | def chooseUniform(lst): 37 | if len(lst) == 0: 38 | return None 39 | return random.choice(list(lst)) 40 | 41 | '''get a random integer between a and b''' 42 | @staticmethod 43 | def randomInt(a,b): 44 | return random.randint(a,b) 45 | 46 | ''' 47 | select an element from a list with the later ones getting more priority by a factor of "factor" times 48 | 49 | if 0 < factor < 1, then priority is given to the starting elements 50 | 51 | if factor > 1 priority given to elements in towards the end 52 | ''' 53 | @staticmethod 54 | def chooseBiased(lst, factor): 55 | size = len(lst) 56 | 57 | if size == 1: 58 | return lst[0] 59 | 60 | x = 0 61 | for i in range(size): 62 | x += factor**i 63 | 64 | prob = (factor**(size-1))*(1.0/(x)) 65 | 66 | return Random.withprobability(prob, lambda: lst[size-1], 67 | lambda: Random.chooseBiased(lst[:-1], factor)) 68 | 69 | @staticmethod 70 | def chooseWeightedBiased(d): 71 | 72 | weights = d.values() 73 | items = d.keys() 74 | prob = weights[0]*(1.0/sum(weights)) 75 | 76 | return Random.withprobability(prob, lambda: items[0], 77 | lambda: Random.chooseWeightedBiased(dict(zip(items[1:],weights[1:])))) 78 | 79 | 80 | @staticmethod 81 | def randomFloat(a,b): 82 | return random.uniform(a, b) 83 | 84 | @staticmethod 85 | def randomBool(): 86 | choice = random.randint(0, 1) 87 | if choice == 0: 88 | return True 89 | else: 90 | return False 91 | 92 | @staticmethod 93 | def randomString(length): 94 | return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length)) 95 | 96 | 97 | if __name__ == '__main__': 98 | import sys 99 | def main(): 100 | 101 | print Random.randomString(10) 102 | return 103 | print Random.chooseWeightedBiased({'a':1, 104 | 'b':5, 105 | 'c':2, 106 | 'd':3}) 107 | 108 | print Random.chooseBiased([111,222,333,444,555,666],1.5) 109 | print Random.probability(0.5) 110 | Random.withprobability(0.9, lambda: sys.stdout.write("YES\n")) 111 | Random.withprobability(0.1, lambda: sys.stdout.write("YES\n"), lambda: sys.stdout.write("NO\n")) 112 | print Random.chooseUniform(range(100,200)) 113 | print Random.randomInt(100,200) 114 | 115 | main() 116 | -------------------------------------------------------------------------------- /PhpIL/program.py: -------------------------------------------------------------------------------- 1 | import opcodes 2 | 3 | class Program: 4 | 5 | def __init__(self, *args): 6 | self.nextVariable = 0 7 | if len(args) == 0: 8 | self.instructionList = [] 9 | elif len(args) == 1: 10 | self.instructionList = args[0] 11 | 12 | def append(self, instruction): 13 | # print instruction 14 | self.instructionList.append(instruction) 15 | 16 | def __str__(self): 17 | string = "" 18 | indentLevel = 0 19 | for i, ins in enumerate(self.instructionList): 20 | 21 | if ins.isBlockEnd() or ins.operation.opcode == opcodes.opcodes.BeginElse: 22 | indentLevel -= 1 23 | string += (str(i) + ": ").ljust(5,' ') + "\t"*indentLevel + str(ins) + "\n" 24 | if ins.isBlockBegin(): 25 | indentLevel += 1 26 | 27 | return string 28 | 29 | if __name__ == '__main__': 30 | import opcodes 31 | import operation 32 | import variable 33 | import instructions 34 | import typesData 35 | 36 | Program([ 37 | instructions.Instruction(operation.Nop()), instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(12)]) 38 | ]) 39 | 40 | Program([ 41 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(0)]), 42 | instructions.Instruction(operation.LoadInteger(9),False,[variable.Variable(3)]), 43 | instructions.Instruction(operation.LoadString("thisisastring"),False,[variable.Variable(1)]), 44 | instructions.Instruction(operation.LoadInteger(True),False,[variable.Variable(4)]), 45 | instructions.Instruction(operation.BeginWhile(">"),[variable.Variable(0), variable.Variable(3)]), 46 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(6)]), 47 | instructions.Instruction(operation.BeginIf(),[variable.Variable(2)]), 48 | instructions.Instruction(operation.LoadString("thisisastring"),False,[variable.Variable(9)]), 49 | instructions.Instruction(operation.EndIf()), 50 | instructions.Instruction(operation.BinaryOperation(">"),[variable.Variable(0),variable.Variable(3)],[variable.Variable(5)]), 51 | instructions.Instruction(operation.EndWhile()), 52 | ]) 53 | 54 | print Program([ 55 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(0)]), 56 | instructions.Instruction(operation.LoadInteger(1), False, [variable.Variable(1)]), 57 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(2)]), 58 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(3)]), 59 | instructions.Instruction(operation.LoadInteger(20), False, [variable.Variable(4)]), 60 | instructions.Instruction(operation.LoadInteger(5), False, [variable.Variable(5)]), 61 | instructions.Instruction(operation.Phi(), [variable.Variable(3)], [variable.Variable(6)]), 62 | instructions.Instruction(operation.Phi(), [variable.Variable(4)], [variable.Variable(7)]), 63 | instructions.Instruction(operation.BeginFor("++", "<"), [variable.Variable(0),variable.Variable(2),variable.Variable(8)]), 64 | instructions.Instruction(operation.BinaryOperation("<"), [variable.Variable(8), variable.Variable(5)], [variable.Variable(6)]), 65 | instructions.Instruction(operation.BeginIf(), [variable.Variable(6)], False), 66 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 67 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 68 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(6), variable.Variable(1)], [variable.Variable(10)]), 69 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 70 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 71 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 72 | instructions.Instruction(operation.EndWhile(), False, False), 73 | 74 | instructions.Instruction(operation.BeginElse(), False, False), 75 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 76 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 77 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(7), variable.Variable(1)], [variable.Variable(10)]), 78 | instructions.Instruction(operation.Copy(), [variable.Variable(7), variable.Variable(10)]), 79 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 80 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 81 | instructions.Instruction(operation.EndWhile(), False, False), 82 | 83 | 84 | instructions.Instruction(operation.EndIf(), False, False), 85 | instructions.Instruction(operation.EndFor(), False, False) 86 | 87 | ]) 88 | 89 | Program() 90 | Program([ 91 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(0)]), 92 | instructions.Instruction(operation.BeginFunction(typesData.FunctionSignature(2)),False,[variable.Variable(1)],[variable.Variable(10),variable.Variable(11)]), 93 | instructions.Instruction(operation.BinaryOperation("+"),[variable.Variable(10),variable.Variable(11)],[variable.Variable(2)]), 94 | instructions.Instruction(operation.LoadString("somestring"),False,[variable.Variable(3)]), 95 | instructions.Instruction(operation.Return(),[variable.Variable(3)]), 96 | instructions.Instruction(operation.EndFunction()), 97 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(4)]), 98 | instructions.Instruction(operation.CallFunction(2),[variable.Variable(1), variable.Variable(4), variable.Variable(0)],[variable.Variable(6)]), 99 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(7)]), 100 | ]) 101 | 102 | 103 | 104 | # print Program([Instruction()]) 105 | -------------------------------------------------------------------------------- /PhpIL/instructions.py: -------------------------------------------------------------------------------- 1 | import operation 2 | import variable 3 | import opcodes 4 | 5 | class Instruction: 6 | 7 | def __init__(self, operation, inputs=False, outputs=False, temp=False): 8 | self.operation = operation 9 | if inputs == False: 10 | self.inputs = [] 11 | else: 12 | self.inputs = inputs 13 | 14 | if outputs == False: 15 | self.outputs = [] 16 | else: 17 | self.outputs = outputs 18 | 19 | if temp == False: 20 | self.temp = [] 21 | else: 22 | self.temp = temp 23 | 24 | def __str__(self): 25 | 26 | string = str(self.operation) 27 | 28 | inps = "" 29 | for i, val in enumerate(self.inputs): 30 | string = string.replace("inp"+str(i), str(val)) 31 | 32 | for i, val in enumerate(self.outputs): 33 | string = string.replace("out"+str(i), str(val)) 34 | 35 | return string 36 | 37 | '''getter for the ith input/output variable''' 38 | def getOutput(self,idx=0): 39 | return self.outputs[idx] 40 | 41 | def getInput(self,idx=0): 42 | return self.inputs[idx] 43 | 44 | def getTemp(self, idx=0): 45 | return self.temp[idx] 46 | 47 | '''getter for all output variable''' 48 | def getAllOutputs(self): 49 | return self.outputs 50 | 51 | def getAllInputs(self): 52 | return self.inputs 53 | 54 | def getAllTemps(self): 55 | return self.temp 56 | 57 | '''misc functions''' 58 | def isBeginFunction(self): 59 | return self.operation.opcode == opcodes.opcodes.BeginFunction 60 | 61 | def isEndFunction(self): 62 | return self.operation.opcode == opcodes.opcodes.EndFunction 63 | 64 | def isBeginElse(self): 65 | return self.operation.opcode == opcodes.opcodes.BeginElse 66 | 67 | def hasOutputs(self): 68 | return self.operation.numOutputs != 0 69 | 70 | def hasInputs(self): 71 | return self.operation.numInputs != 0 72 | 73 | def getOpcode(self): 74 | return self.operation.opcode 75 | 76 | 77 | '''Flag operations''' 78 | def isBlockBegin(self): 79 | return self.operation.getFlags() & self.operation.Attributes.isBlockBegin 80 | 81 | def isBlockEnd(self): 82 | return self.operation.getFlags() & self.operation.Attributes.isBlockEnd 83 | 84 | def isLoopBegin(self): 85 | return self.operation.getFlags() & operation.Operation.Attributes.isLoopBegin 86 | 87 | def isLoopEnd(self): 88 | return self.operation.getFlags() & operation.Operation.Attributes.isLoopEnd 89 | 90 | 91 | 92 | if __name__ == '__main__': 93 | '''Tests''' 94 | def main(): 95 | print Instruction(operation.Nop()) 96 | print Instruction(operation.LoadInteger(1),False,[variable.Variable(12)]) 97 | print Instruction(operation.LoadFloat(1.1),False,[variable.Variable(11)]) 98 | print Instruction(operation.LoadString('aaaa'),False,[variable.Variable(12)]) 99 | print Instruction(operation.LoadBoolean(True),False,[variable.Variable(12)]) 100 | print Instruction(operation.LoadNull(),False,[variable.Variable(12)]) 101 | print Instruction(operation.CreateArray(3),[variable.Variable(2),variable.Variable(3),variable.Variable(4)],[variable.Variable(12)]) 102 | print Instruction(operation.CallFunction(2),[variable.Variable(1), variable.Variable(2), variable.Variable(3)], [variable.Variable(4)]) 103 | #print Instruction(operation.CreateObject('blag', 3),[variable.Variable(1),variable.Variable(3),variable.Variable(2) ],[variable.Variable(12)]) //Error 104 | #print Instruction(operation.BeginFunction(),False,[variable.Variable(12)]) //NotCompleted 105 | #print Instruction(operation.EndFunction(),False,False) //NotCompleted 106 | print Instruction(operation.BeginIf(),[variable.Variable(1)],False) 107 | print Instruction(operation.BeginElse(),False,False) 108 | print Instruction(operation.EndIf(),False,False) 109 | print Instruction(operation.BeginWhile(">"),[variable.Variable(5), variable.Variable(0)],False) # Error 110 | print Instruction(operation.EndWhile(),False,False) 111 | print Instruction(operation.BeginFor("++", "<"),[variable.Variable(1), variable.Variable(4), variable.Variable(10)],False) 112 | print Instruction(operation.EndFor(),False,False) 113 | #print Instruction(operation.BeginForEach(),False,False) //NotCompleted 114 | #print Instruction(operation.EndForEach(),False,False) //NotCompleted 115 | print Instruction(operation.Return(),False,[variable.Variable(12)]) 116 | print Instruction(operation.Break(),False,False) 117 | print Instruction(operation.Continue(),False,False) 118 | #print Instruction(operation.BeginTry(),False,False) //NotCompleted 119 | #print Instruction(operation.BeginCatch(),False,False) //NotCompleted 120 | #print Instruction(operation.EndTryCatch(),False,False) //NotCompleted 121 | #print Instruction(operation.BeginClass(),False,False) //NotMade 122 | #print Instruction(operation.EndClass(),False,False) //NotMade 123 | print Instruction(operation.UnaryOperation("++"),[variable.Variable(11)],[variable.Variable(10)]) 124 | print Instruction(operation.BinaryOperation("+"),[variable.Variable(10), variable.Variable(11)],[variable.Variable(10)]) 125 | print Instruction(operation.Include(),[variable.Variable("module")],False) 126 | print Instruction(operation.Eval('1'),[variable.Variable(11)],False) 127 | print Instruction(operation.Phi(), [variable.Variable(10)], [variable.Variable(12)]) 128 | print Instruction(operation.Copy(), [variable.Variable(10), variable.Variable(20)], False) 129 | print Instruction(operation.ThrowException(), [variable.Variable(10)], False) 130 | print Instruction(operation.BeginTry(), False, False) 131 | print Instruction(operation.Copy(),False, [variable.Variable(20)]) 132 | print Instruction(operation.Print(), [variable.Variable(10)], False) 133 | print Instruction(operation.BeginDoWhile(), False, False) 134 | print Instruction(operation.EndDoWhile(">"), [variable.Variable(1), variable.Variable(2)], False) 135 | 136 | #def tests(): 137 | # a = Instruction(operation.BeginWhile(">"),[variable.Variable(5), variable.Variable(0)],False) 138 | # print a.isBeginFunction() 139 | 140 | #tests() 141 | 142 | 143 | main() 144 | -------------------------------------------------------------------------------- /PhpIL/code_generators.py: -------------------------------------------------------------------------------- 1 | import program_builder 2 | import typesData 3 | import variable 4 | import operation 5 | import probability 6 | 7 | class CodeGenerator: 8 | 9 | # def __init__(self, obj): 10 | # print "__init__" 11 | # #Assigning the object of programBuilder 12 | # programBuilder = obj; 13 | 14 | @staticmethod 15 | def integerLiteralGenerator(programBuilder): 16 | # print "integerLiteralGenerator" 17 | programBuilder.loadInteger(programBuilder.getInt()) 18 | return True 19 | 20 | @staticmethod 21 | def floatLiteralGenerator(programBuilder): 22 | # print "floatLiteralGenerator" 23 | programBuilder.loadFloat(programBuilder.getFloat()) 24 | return True 25 | 26 | @staticmethod 27 | def stringLiteralGenerator(programBuilder): 28 | # print "stringLiteralGenerator" 29 | programBuilder.loadString(programBuilder.getString()) 30 | return True 31 | 32 | @staticmethod 33 | def booleanLiteralGenerator(programBuilder): 34 | # print "booleanLiteralGenerator" 35 | programBuilder.loadBoolean(probability.Random.randomBool()) 36 | return True 37 | 38 | @staticmethod 39 | def nullValueGenerator(programBuilder): 40 | # print "nullValueGenerator" 41 | programBuilder.loadNull() 42 | return True 43 | 44 | @staticmethod 45 | def intArrayGenerator(programBuilder): 46 | # print "intArrayGenerator" 47 | initial = [] 48 | for i in range(probability.Random.randomInt(0,10)): 49 | initial.append(probability.Random.randomInt(0,6)) 50 | programBuilder.createArray(initial) 51 | return True 52 | 53 | 54 | @staticmethod 55 | def dictGenerator(programBuilder): 56 | # print "dictGenerator" 57 | initial = [] 58 | for i in range(probability.Random.randomInt(0,10)): 59 | key = probability.Random.withEqualProbability( 60 | lambda: programBuilder.getInt(), 61 | lambda: programBuilder.getFloat(), 62 | lambda: programBuilder.randVar(), 63 | ) 64 | 65 | value = probability.Random.withEqualProbability( 66 | lambda: programBuilder.getInt(), 67 | lambda: programBuilder.getFloat(), 68 | lambda: programBuilder.randVar(), 69 | ) 70 | 71 | initial.append((key,value)) 72 | 73 | programBuilder.createDict(initial) 74 | return True 75 | 76 | @staticmethod 77 | def floatArrayGenerator(programBuilder): 78 | # print "floatArrayGenerator" 79 | initial = [] 80 | for i in range(probability.Random.randomInt(0,10)): 81 | initial.append(probability.Random.randomFloat(0,6)) 82 | programBuilder.createArray(initial) 83 | return True 84 | 85 | @staticmethod 86 | def unaryOperationGenerator(programBuilder): 87 | # print "unaryOperationGenerator" 88 | input = programBuilder.randVar(type = (typesData.Types.Integer) ) 89 | programBuilder.unaryOperation(probability.Random.chooseUniform(operation.UnaryOperator.all()),input ) 90 | return True 91 | 92 | @staticmethod 93 | def binaryOperationGenerator(programBuilder): 94 | # print "binaryOperationGenerator" 95 | lhs = programBuilder.randVar() 96 | rhs = programBuilder.randVar() 97 | programBuilder.binaryOperation(lhs, rhs, probability.Random.chooseUniform(operation.BinaryOperator.all())) 98 | return True 99 | 100 | #Create phi function in program_builder.py 101 | @staticmethod 102 | def phiGenerator(programBuilder): 103 | # print "phiGenerator" 104 | programBuilder.phi(programBuilder.randVar()) 105 | return True 106 | 107 | @staticmethod 108 | def whileLoopGenerator(programBuilder): 109 | # print "whileLoopGenerator" 110 | start = programBuilder.loadInteger(0) 111 | end = programBuilder.loadInteger(probability.Random.randomInt(0,10)) 112 | loopVar = programBuilder.phi(start) 113 | programBuilder.beginWhile(loopVar, "<", end) 114 | programBuilder.unaryOperation("++", loopVar) 115 | programBuilder.generateRandomInst() 116 | programBuilder.endWhile() 117 | 118 | return True 119 | 120 | 121 | @staticmethod 122 | def doWhileLoopGenerator(programBuilder): 123 | start = programBuilder.loadInteger(0) 124 | end = programBuilder.loadInteger(probability.Random.randomInt(0,10)) 125 | loopVar = programBuilder.phi(start) 126 | programBuilder.beginDoWhile() 127 | programBuilder.unaryOperation("++", loopVar) 128 | programBuilder.generateRandomInst() 129 | programBuilder.endDoWhile(loopVar, "<", end) 130 | 131 | @staticmethod 132 | def ifStatementGenerator(programBuilder): 133 | # print "ifStatementGenerator" 134 | cond = programBuilder.randVar(type=typesData.Types.Boolean) 135 | a = programBuilder.randVar() 136 | phi = programBuilder.phi(a) 137 | programBuilder.beginIf(cond) 138 | programBuilder.generateRandomInst() 139 | programBuilder.copy(phi, programBuilder.randVar()) 140 | programBuilder.beginElse() 141 | programBuilder.generateRandomInst() 142 | programBuilder.copy(phi, programBuilder.randVar()) 143 | programBuilder.endIf() 144 | 145 | return True 146 | 147 | 148 | @staticmethod 149 | def forLoopGenerator(programBuilder): 150 | # print "forLoopGenerator" 151 | start = programBuilder.loadInteger(0) 152 | end = programBuilder.loadInteger(probability.Random.randomInt(0,10)) 153 | # programBuilder.binaryOperation() 154 | step = programBuilder.loadInteger(1) 155 | programBuilder.beginFor(start, "<", end, "+", step) 156 | programBuilder.generateRandomInst() 157 | programBuilder.endFor() 158 | 159 | 160 | @staticmethod 161 | def breakGenerator(programBuilder): 162 | # print "breakGenerator" 163 | if programBuilder.lastContextisLoop(): 164 | programBuilder.doBreak() 165 | return True 166 | return False 167 | 168 | 169 | @staticmethod 170 | def continueGenerator(programBuilder): 171 | # print "continueGenerator" 172 | if programBuilder.lastContextisLoop(): 173 | programBuilder.doContinue() 174 | return True 175 | return False 176 | 177 | @staticmethod 178 | def functionDefinationGenerator(programBuilder): 179 | # print "functionDefinationGenerator" 180 | visbleVars = programBuilder.getVisibleVars() 181 | usableVars = [] 182 | for i in visbleVars: 183 | if programBuilder.typeAnalyzer.getType(i) == typesData.Types.Function and programBuilder.typeAnalyzer.getSignature(i).isConstructing(): 184 | continue 185 | usableVars.append(i) 186 | signature = typesData.FunctionSignature(probability.Random.randomInt(1,5), usableVars) 187 | function = programBuilder.functionDefination(signature) 188 | programBuilder.generateRandomInst() 189 | returnValue = programBuilder.randVar() 190 | CodeGenerator.functionReturnGenerator(programBuilder) 191 | programBuilder.endFunction() 192 | 193 | 194 | # programBuilder.generateRandomInst() 195 | programBuilder.generateRandomInst() 196 | arguments = programBuilder.generateCallArguments(function) 197 | if not isinstance(arguments, list): 198 | return False 199 | programBuilder.callFunction(function, arguments) 200 | 201 | return True 202 | 203 | @staticmethod 204 | def functionReturnGenerator(programBuilder): 205 | # print "functionReturnGenerator" 206 | if programBuilder.isInFunction(): 207 | programBuilder.doReturn(programBuilder.randVar()) 208 | return True 209 | return False 210 | 211 | @staticmethod 212 | def functionCallGenerator(programBuilder): 213 | # print "functionCallGenerator" 214 | function = programBuilder.randVar(type = typesData.Types.Function) 215 | if not isinstance(function, variable.Variable): 216 | return False 217 | # recursive = programBuilder.checkRecursion(function) 218 | # if recursive: 219 | # return False 220 | arguments = programBuilder.generateCallArguments(function) 221 | if not isinstance(arguments, list): 222 | return False 223 | programBuilder.callFunction(function, arguments) 224 | return True 225 | 226 | @staticmethod 227 | def tryCatchGenerator(programBuilder): 228 | # print "tryCatchGenerator" 229 | v = programBuilder.phi(programBuilder.randVar()) 230 | programBuilder.beginTry() 231 | programBuilder.generateRandomInst() 232 | programBuilder.copy(programBuilder.randVar(), v) 233 | programBuilder.beginCatch() 234 | # programBuilder.generateRandomInst() 235 | programBuilder.copy(programBuilder.randVar(), v) 236 | programBuilder.endTryCatch() 237 | 238 | @staticmethod 239 | def throwGenerator(programBuilder): 240 | # print "throwGenerator" 241 | v = programBuilder.randVar() 242 | programBuilder.throwException(v) 243 | 244 | @staticmethod 245 | def arrayLiteralGenerator(programBuilder): 246 | # print "arrayLiteralGenerator" 247 | initial = [] 248 | for i in range(probability.Random.randomInt(0,6)): 249 | initial.append(programBuilder.randVar()) 250 | programBuilder.createArray(initial) 251 | return True 252 | 253 | @staticmethod 254 | def getArrayElemGenerator(programBuilder): 255 | # print "getArrayElemGenerator" 256 | arr = programBuilder.randVar(type = typesData.Types.Array) 257 | if not arr: 258 | arr = programBuilder.randVar(type = typesData.Types.String) 259 | 260 | lst = range(probability.Random.randomInt(0,10)) 261 | temp = programBuilder.getInt() 262 | lst.append(temp) 263 | index = probability.Random.chooseUniform(lst) 264 | programBuilder.getArrayElem(arr, index) 265 | return True 266 | 267 | @staticmethod 268 | def setArrayElemGenerator(programBuilder): 269 | # print "setArrayElemGenerator" 270 | arr = programBuilder.randVar(type = typesData.Types.Array) 271 | if not arr: 272 | arr = programBuilder.randVar(type = typesData.Types.String) 273 | 274 | lst = range(probability.Random.randomInt(0,10)) 275 | temp = programBuilder.getInt() 276 | lst.append(temp) 277 | index = probability.Random.chooseUniform(lst) 278 | value = programBuilder.randVar() 279 | programBuilder.setArrayElem(arr, index, value) 280 | return True 281 | 282 | 283 | #objectLiteralGenerator not created. 284 | #objectLiteralWithSpreadGenerator not created 285 | #builinGenerator not created 286 | #functionDefinationGenerator not created 287 | #propertyRetrievalGenerator not created 288 | #propertyAssignmentGenerator not created 289 | #propertyRemovalGenerator not created 290 | #elementRetrievalGenerator not created 291 | #elementAssignmentGenerator not created 292 | #elementRemovalGenerator not created 293 | #computedPropertyAssignmentGenerator not created 294 | #computedPropertyRetrievalGenerator not created 295 | #computedPropertyRemovalGenerator not created 296 | #typeTestGenerator not created 297 | #instanceOfGenerator not created 298 | #inGenerator not created 299 | #methodCallGenerator not created 300 | #functionCallGenerator not created 301 | #constructorCallGenerator not created 302 | #functionCallWithSpreadGenerator not created 303 | #reassignmentGenerator not created 304 | #comparisonGenerator not created 305 | #ifStatementGenerator not created *** 306 | -------------------------------------------------------------------------------- /PhpIL/program_builder.py: -------------------------------------------------------------------------------- 1 | import program 2 | import instructions 3 | import typesData 4 | import analyzer 5 | import variable 6 | import operation 7 | import probability 8 | import settings 9 | from code_generators import CodeGenerator 10 | 11 | class ProgramBuilder: 12 | 13 | def __init__(self, prog=False): 14 | if prog == False: 15 | self.program = program.Program() 16 | else: 17 | self.program = prog 18 | 19 | self.nextFreeVariable = self.program.nextVariable 20 | self.instructionList = [] 21 | for i in self.program.instructionList: 22 | self.instructionList.append(i) 23 | 24 | self.seenIntegers = set([]) 25 | self.seenFloats = set([]) 26 | self.seenStrings = set([]) 27 | 28 | self.scopeAnalyzer = analyzer.ScopeAnalyzer(self.program) 29 | self.scopeAnalyzer.doAnalyze() 30 | 31 | self.contextAnalyzer = analyzer.ContextAnalyzer(self.program) 32 | self.contextAnalyzer.doAnalyze() 33 | 34 | self.typeAnalyzer = analyzer.TypeAnalyzer(self.program) 35 | self.typeAnalyzer.doAnalyze() 36 | 37 | 38 | '''Append a given instruction to the current program after performing analysis''' 39 | def instructionAppend(self, inst): 40 | # print inst 41 | self.scopeAnalyzer.analyze(inst) 42 | self.contextAnalyzer.analyze(inst) 43 | self.typeAnalyzer.analyze(inst) 44 | self.instructionList.append(inst) 45 | 46 | ''''Utility functions start''' 47 | 48 | '''finish this program builder and save the instructions to the program''' 49 | def finish(self): 50 | for i in self.instructionList: 51 | self.program.append(i) 52 | 53 | return self.program 54 | 55 | '''get variables of type "type" ''' 56 | def randVar(self, type=typesData.Types.Unknown, strict=0): 57 | 58 | candidates = [] 59 | iter = 2*len(self.scopeAnalyzer.scopes) 60 | while len(candidates) == 0 and iter > 0: 61 | candidates = probability.Random.chooseBiased(self.scopeAnalyzer.scopes, 6) 62 | candidates = filter(lambda x: self.typeAnalyzer.getType(x) == type or self.typeAnalyzer.getType(x) == typesData.Types.Unknown, candidates) 63 | iter -= 1 64 | 65 | if len(candidates) == 0: 66 | if type == typesData.Types.Boolean: 67 | candidates = [self.loadBoolean(probability.Random.randomBool())] 68 | if type == typesData.Types.String: 69 | candidates = [self.loadString(self.getString())] 70 | if type == typesData.Types.Float: 71 | candidates = [self.loadFloat(self.getFloat())] 72 | if type == typesData.Types.Integer: 73 | candidates = [self.loadInteger(self.getInt())] 74 | 75 | if type == typesData.Types.Unknown: 76 | while len(candidates) == 0: 77 | candidates = probability.Random.chooseBiased(self.scopeAnalyzer.scopes, 5) 78 | 79 | 80 | 81 | if len(candidates) == 0: 82 | return False 83 | # print candidates 84 | ret = probability.Random.chooseUniform(candidates) 85 | # print ret, self.typeAnalyzer.getType(ret) 86 | return ret 87 | 88 | def generateRandomInst(self): 89 | ret = False 90 | if len(self.scopeAnalyzer.getVisibleVars()) == 0: 91 | codegens = [ 92 | CodeGenerator.nullValueGenerator, 93 | CodeGenerator.booleanLiteralGenerator, 94 | CodeGenerator.floatLiteralGenerator, 95 | CodeGenerator.stringLiteralGenerator, 96 | CodeGenerator.integerLiteralGenerator 97 | ] 98 | 99 | return probability.Random.chooseBiased(codegens,1.5)(self) 100 | 101 | while not ret: 102 | choice = probability.Random.chooseWeightedBiased(settings.Settings.allCodeGenerators) 103 | ret = choice(self) 104 | 105 | def getInt(self): 106 | def selectFromSeen(): 107 | return probability.Random.chooseUniform(list(self.seenIntegers)) 108 | def createNew(): 109 | return probability.Random.randomInt(-0x1000, 0x1000) 110 | 111 | ret = None 112 | while ret == None: 113 | ret = probability.Random.withprobability(0.50, selectFromSeen, createNew) 114 | 115 | self.seenIntegers.add(ret) 116 | 117 | return ret 118 | 119 | 120 | def getFloat(self): 121 | def selectFromSeen(): 122 | return probability.Random.chooseUniform(list(self.seenFloats)) 123 | def createNew(): 124 | return probability.Random.randomFloat(-0x1000, 0x1000) 125 | 126 | ret = None 127 | while ret == None: 128 | ret = probability.Random.withprobability(0.50, selectFromSeen, createNew) 129 | 130 | self.seenFloats.add(ret) 131 | 132 | return ret 133 | 134 | def getString(self): 135 | def selectFromSeen(): 136 | return probability.Random.chooseUniform(list(self.seenStrings)) 137 | def createNew(): 138 | return probability.Random.randomString(probability.Random.randomInt(0,10)) 139 | 140 | ret = None 141 | while ret == None: 142 | ret = probability.Random.withprobability(0.50, selectFromSeen, createNew) 143 | 144 | self.seenStrings.add(ret) 145 | 146 | return ret 147 | 148 | def isInLoop(self): 149 | return self.contextAnalyzer.isInLoopContext() 150 | 151 | def isInFunction(self): 152 | return self.contextAnalyzer.isInFunctionContext() 153 | 154 | def lastContextisLoop(self): 155 | return self.contextAnalyzer.lastContextisLoop() 156 | 157 | def getOuterVars(self): 158 | return self.scopeAnalyzer.getOuterVisibleVars() 159 | 160 | def getVisibleVars(self): 161 | return self.scopeAnalyzer.getVisibleVars() 162 | 163 | def generateCallArguments(self, function): 164 | signature = self.typeAnalyzer.getSignature(function) 165 | if not isinstance(signature, typesData.FunctionSignature): 166 | return False 167 | argsTypes = signature.getInputTypes() 168 | arguments = [] 169 | for type in argsTypes: 170 | arguments.append(self.randVar(type)) 171 | 172 | return arguments 173 | 174 | 175 | ''''Utility functions end''' 176 | 177 | 178 | '''Returns the next free variable for this program''' 179 | def nextVariable(self): 180 | self.nextFreeVariable += 1 181 | return variable.Variable(self.nextFreeVariable-1) 182 | 183 | '''Assign variables and convert the given operation into an instruction''' 184 | def perform(self, ops, inputs=False): 185 | outputs = [] 186 | tempVars = [] 187 | for i in range(ops.numOutputs): 188 | outputs.append(self.nextVariable()) 189 | for i in range(ops.numTempvars): 190 | tempVars.append(self.nextVariable()) 191 | 192 | if outputs == []: 193 | outputs = False 194 | if tempVars == []: 195 | tempVars = False 196 | 197 | inst = instructions.Instruction(ops, inputs, outputs, tempVars) 198 | self.instructionAppend(inst) 199 | 200 | return inst 201 | 202 | '''Instructions in PHPIL added to this program''' 203 | 204 | def nop(self): 205 | return self.perform(operation.Nop()).getOutput() 206 | 207 | def loadInteger(self, value): 208 | return self.perform(operation.LoadInteger(value)).getOutput() 209 | 210 | def loadFloat(self, value): 211 | return self.perform(operation.LoadFloat(value)).getOutput() 212 | 213 | def loadString(self, value): 214 | return self.perform(operation.LoadString(value)).getOutput() 215 | 216 | def loadBoolean(self, value): 217 | return self.perform(operation.LoadBoolean(value)).getOutput() 218 | 219 | def loadNull(self): 220 | return self.perform(operation.LoadNull()).getOutput() 221 | 222 | def createObject(self, object, args, fieldValues): 223 | return self.perform(operation.CreateObject(object, args, fieldValues)).getOutput() 224 | 225 | def createArray(self, initialValues): 226 | return self.perform(operation.CreateArray(len(initialValues)), initialValues).getOutput() 227 | 228 | def callFunction(self, funcName, args): 229 | return self.perform(operation.CallFunction(len(args) + 1), [funcName] + args).getOutput() 230 | 231 | def doPrint(self, value): 232 | return self.perform(operation.Print(), [value]).getOutput() 233 | 234 | #beginFunction is not finished in operation.py 235 | def beginFunction(self): 236 | return self.perform(operation.BeginFunction()).getOutput() 237 | 238 | #endFunction is not finished in operation.py 239 | def endFunction(self): 240 | return self.perform(operation.EndFunction()) 241 | 242 | 243 | def beginIf(self, conditional): 244 | return self.perform(operation.BeginIf(), [conditional]) 245 | 246 | def beginElse(self): 247 | return self.perform(operation.BeginElse()) 248 | 249 | def endIf(self): 250 | return self.perform(operation.EndIf()) 251 | 252 | def beginWhile(self, lhs, comparater, rhs): 253 | return self.perform(operation.BeginWhile(comparater), [lhs, rhs]) 254 | 255 | def endWhile(self): 256 | return self.perform(operation.EndWhile()) 257 | 258 | def beginFor(self, start, comparater, end, op, rhs): 259 | return self.perform(operation.BeginFor(op, comparater), [start, end, rhs]) 260 | 261 | def copy(self, inp, out): 262 | return self.perform(operation.Copy(), [inp, out]) 263 | 264 | def endFor(self): 265 | self.perform(operation.EndFor()) 266 | 267 | def beginDoWhile(self): 268 | return self.perform(operation.BeginDoWhile()) 269 | 270 | def endDoWhile(self, lhs, comparater, rhs): 271 | return self.perform(operation.EndDoWhile(comparater), [lhs, rhs]) 272 | 273 | #beginForEach notDefined in operation.py 274 | def beginForEach(self): 275 | return self.perform(operation.BeginForEach()) 276 | 277 | def endForEach(self): 278 | return self.perform(operation.EndForEach()) 279 | 280 | def doReturn(self, value): 281 | return self.perform(operation.Return(), [value]) 282 | 283 | def doBreak(self): 284 | return self.perform(operation.Break(), []) 285 | 286 | def doContinue(self): 287 | return self.perform(operation.Continue(), []) 288 | 289 | def beginTry(self): 290 | return self.perform(operation.BeginTry()) 291 | 292 | def beginCatch(self): 293 | return self.perform(operation.BeginCatch()) 294 | 295 | def endTryCatch(self): 296 | return self.perform(operation.EndTryCatch()) 297 | 298 | #BeginClass not completed in operation.py 299 | def beginClass(self): 300 | return self.perform(operation.BeginClass()).getOutput() 301 | 302 | #EndClass not completed in operation.py 303 | def endClass(self): 304 | return self.perform(operation.EndClass()).getOutput() 305 | 306 | def unaryOperation(self, op, input): 307 | return self.perform(operation.UnaryOperation(op), [input]).getOutput() 308 | 309 | #check binaryOperation function once again 310 | def binaryOperation(self, lhs, rhs, op): 311 | return self.perform(operation.BinaryOperation(op), [lhs, rhs]).getOutput() 312 | 313 | def functionDefination(self, signature): 314 | return self.perform(operation.BeginFunction(signature)).getOutput() 315 | 316 | def doInclude(self, value): 317 | return self.perform(operation.Include(), [value]) 318 | 319 | #check doEval 320 | def doEval(self, string, arguments): 321 | return self.perform(operation.Eval(string, len(argummets)), arguments).getOutput() 322 | 323 | def phi(self, var): 324 | return self.perform(operation.Phi(), [var]).getOutput() 325 | 326 | def createDict(self, dictElements): 327 | return self.perform(operation.CreateDict(len(dictElements)), dictElements).getOutput() 328 | 329 | def getArrayElem(self, arr, elem): 330 | return self.perform(operation.GetArrayElem(), [arr,elem]).getOutput() 331 | 332 | def setArrayElem(self, arr, elem, value): 333 | return self.perform(operation.SetArrayElem(), [arr,elem,value]) 334 | 335 | 336 | #ThrowException not completed in operation.py 337 | def throwException(self, value): 338 | return self.perform(operation.ThrowException(), [value]) 339 | 340 | if __name__ == '__main__': 341 | def main(): 342 | a = ProgramBuilder() 343 | out1 = [] 344 | out2 = [] 345 | out3 = [] 346 | for i in range(10): 347 | out1.append(a.getInt()) 348 | out2.append(a.getFloat()) 349 | out3.append(a.getString()) 350 | print out1 351 | print out2 352 | print out3 353 | 354 | main() 355 | -------------------------------------------------------------------------------- /PhpIL/operation.py: -------------------------------------------------------------------------------- 1 | import opcodes 2 | 3 | class Operation(object): 4 | 5 | class Attributes: 6 | isPrimitive = 1 << 0 7 | isLiteral = 1 << 1 8 | isParametric = 1 << 2 9 | isCall = 1 << 3 10 | isBlockBegin = 1 << 4 11 | isBlockEnd = 1 << 5 12 | isLoopBegin = 1 << 6 13 | isLoopEnd = 1 << 7 14 | isInternal = 1 << 8 15 | isJump = 1 << 9 16 | isImmutable = 1 << 10 17 | isVarargs = 1 << 11 18 | 19 | def __init__(self, numInputs, numOutputs, numTempvars, attributes=[]): 20 | self.opcode = 0 21 | self.numInputs = numInputs 22 | self.numOutputs = numOutputs 23 | self.numTempvars = numTempvars 24 | self.attributes = attributes 25 | self.flags = 0 26 | for i in attributes: 27 | self.flags |= i 28 | 29 | def getFlags(self): 30 | return self.flags 31 | 32 | def __str__(self): 33 | outstring = "" 34 | output = "" 35 | input = "" 36 | 37 | for i in range(self.numOutputs): 38 | output += "out" + str(i) + ", " 39 | 40 | if self.numOutputs > 0: 41 | output = ''.join(output.rsplit(',', 1)) + "= " 42 | 43 | for i in range(self.numInputs): 44 | input += "inp" + str(i) + ", " 45 | 46 | if self.numInputs > 0: 47 | input = ''.join(input.rsplit(',', 1)) + "" 48 | 49 | return output + opcodes.opcodes.opcodeList[self.opcode] + " " + input 50 | 51 | class Nop(Operation): 52 | def __init__(self): 53 | super(Nop, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isPrimitive]) 54 | self.opcode = opcodes.opcodes.Nop 55 | 56 | class LoadInteger(Operation): 57 | def __init__(self, value): 58 | super(LoadInteger, self).__init__(numInputs=0, numOutputs=1, numTempvars=0) 59 | self.opcode = opcodes.opcodes.LoadInteger 60 | self.value = value 61 | 62 | def __str__(self): 63 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " " + "'" + str(self.value) + "'" 64 | 65 | class LoadFloat(Operation): 66 | def __init__(self, value): 67 | super(LoadFloat, self).__init__(numInputs=0, numOutputs=1, numTempvars=0) 68 | self.opcode = opcodes.opcodes.LoadFloat 69 | self.value = value 70 | 71 | def __str__(self): 72 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " " + "'" + str(self.value) + "'" 73 | 74 | class LoadString(Operation): 75 | def __init__(self, value): 76 | super(LoadString, self).__init__(numInputs=0, numOutputs=1, numTempvars=0) 77 | self.opcode = opcodes.opcodes.LoadString 78 | self.value = value 79 | 80 | def __str__(self): 81 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " " + "'" + str(self.value) + "'" 82 | 83 | class LoadBoolean(Operation): 84 | def __init__(self, value): 85 | super(LoadBoolean, self).__init__(numInputs=0, numOutputs=1, numTempvars=0) 86 | self.opcode = opcodes.opcodes.LoadBoolean 87 | self.value = value 88 | 89 | def __str__(self): 90 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " " + "'" + str(self.value) + "'" 91 | 92 | class LoadNull(Operation): 93 | def __init__(self): 94 | super(LoadNull, self).__init__(numInputs=0, numOutputs=1, numTempvars=0) 95 | self.opcode = opcodes.opcodes.LoadNull 96 | 97 | # class LoadObject (Operation): 98 | # def __init__(self, value): 99 | #(LoadObject , self) super.__init__(numInputs=0, numOutputs=1, numTempvars=0) 100 | # self.opcode = opcodes.opcodes.LoadObject 101 | # self.value = value 102 | 103 | class CreateObject(Operation): 104 | def __init__(self, object, args): 105 | super(CreateObject, self).__init__(numInputs=1, numOutputs=1, numTempvars=0) 106 | self.opcode = opcodes.opcodes.CreateObject 107 | self.object = object 108 | self.args = args 109 | 110 | class CreateArray(Operation): 111 | def __init__(self, numInitialValues): 112 | super(CreateArray, self).__init__(numInputs=numInitialValues, numOutputs=1, numTempvars=0) 113 | self.opcode = opcodes.opcodes.CreateArray 114 | 115 | class CallFunction(Operation): 116 | def __init__(self, numArgs): 117 | super(CallFunction, self).__init__(numInputs=numArgs+1, numOutputs=1, numTempvars=0) 118 | self.opcode = opcodes.opcodes.CallFunction 119 | 120 | class BeginIf(Operation): 121 | def __init__(self): 122 | super(BeginIf, self).__init__(numInputs=1, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockBegin]) 123 | self.opcode = opcodes.opcodes.BeginIf 124 | 125 | 126 | class BeginElse(Operation): 127 | def __init__(self): 128 | super(BeginElse, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockBegin, Operation.Attributes.isBlockEnd]) 129 | self.opcode = opcodes.opcodes.BeginElse 130 | 131 | 132 | class EndIf(Operation): 133 | def __init__(self): 134 | super(EndIf, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockEnd]) 135 | self.opcode = opcodes.opcodes.EndIf 136 | 137 | 138 | class BeginWhile(Operation): 139 | def __init__(self, comparater): 140 | super(BeginWhile, self).__init__(numInputs=2, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockBegin, Operation.Attributes.isLoopBegin]) 141 | self.opcode = opcodes.opcodes.BeginWhile 142 | self.comparater = comparater 143 | 144 | def __str__(self): 145 | input = " inp0, " + str(self.comparater) + ", inp1" 146 | return opcodes.opcodes.opcodeList[self.opcode] + input 147 | 148 | 149 | class EndWhile(Operation): 150 | def __init__(self): 151 | super(EndWhile, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockEnd, Operation.Attributes.isLoopEnd]) 152 | self.opcode = opcodes.opcodes.EndWhile 153 | 154 | class BeginFor(Operation): 155 | def __init__(self, comparater, op): 156 | super(BeginFor, self).__init__(numInputs=3, numOutputs=0, numTempvars=1, attributes=[Operation.Attributes.isBlockBegin, Operation.Attributes.isLoopBegin]) 157 | self.opcode = opcodes.opcodes.BeginFor 158 | self.op = op 159 | self.comparater = comparater 160 | 161 | def __str__(self): 162 | input = " inp0, "+str(self.op)+" , inp1, "+str(self.comparater)+" ,inp2" 163 | return opcodes.opcodes.opcodeList[self.opcode] + input 164 | 165 | class EndFor(Operation): 166 | def __init__(self): 167 | super(EndFor, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockEnd, Operation.Attributes.isLoopEnd]) 168 | self.opcode = opcodes.opcodes.EndFor 169 | 170 | class BeginDoWhile(Operation): 171 | def __init__(self): 172 | super(BeginDoWhile, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockBegin, Operation.Attributes.isLoopBegin]) 173 | self.opcode = opcodes.opcodes.BeginDoWhile 174 | 175 | class EndDoWhile(Operation): 176 | def __init__(self, comparater): 177 | super(EndDoWhile, self).__init__(numInputs=2, numOutputs=0, numTempvars=0, attributes=[Operation.Attributes.isBlockEnd, Operation.Attributes.isLoopEnd]) 178 | self.opcode = opcodes.opcodes.EndDoWhile 179 | self.comparater = comparater 180 | 181 | class EndForEach(Operation): 182 | def __init__(self): 183 | super(EndForEach, self).__init__(numInputs=0, numOutputs=0, numTempvars=0) 184 | self.opcode = opcodes.opcodes.EndIf 185 | 186 | class Return(Operation): 187 | def __init__(self): 188 | super(Return, self).__init__(numInputs=1, numOutputs=0, numTempvars=0) 189 | self.opcode = opcodes.opcodes.Return 190 | 191 | class Break(Operation): 192 | def __init__(self): 193 | super(Break, self).__init__(numInputs=0, numOutputs=0, numTempvars=0) 194 | self.opcode = opcodes.opcodes.Break 195 | 196 | class Continue(Operation): 197 | def __init__(self): 198 | super(Continue, self).__init__(numInputs=0, numOutputs=0, numTempvars=0) 199 | self.opcode = opcodes.opcodes.Continue 200 | 201 | class UnaryOperation(Operation): 202 | def __init__(self, op): 203 | super(UnaryOperation, self).__init__(numInputs=1, numOutputs=1, numTempvars=0) 204 | self.opcode = opcodes.opcodes.UnaryOperation 205 | self.op = op 206 | 207 | def __str__(self): 208 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " " + str(self.op) + " inp0" 209 | 210 | class BinaryOperation(Operation): 211 | def __init__(self, op): 212 | super(BinaryOperation, self).__init__(numInputs=2, numOutputs=1, numTempvars=0) 213 | self.opcode = opcodes.opcodes.BinaryOperation 214 | self.op = op 215 | 216 | def __str__(self): 217 | return "out0 = " + opcodes.opcodes.opcodeList[self.opcode] + " inp0, " + str(self.op) + " ,inp1" 218 | 219 | 220 | class Include(Operation): 221 | def __init__(self): 222 | super(Include, self).__init__(numInputs=1, numOutputs=0, numTempvars=0) 223 | self.opcode = opcodes.opcodes.Include 224 | 225 | class Eval(Operation): 226 | def __init__(self, value): 227 | super(Eval, self).__init__(numInputs=1, numOutputs=0, numTempvars=0) 228 | self.opcode = opcodes.opcodes.Eval 229 | self.value = value 230 | 231 | 232 | class Phi(Operation): 233 | def __init__(self): 234 | super(Phi, self).__init__(numInputs = 1, numOutputs = 1, numTempvars = 0) 235 | self.opcode = opcodes.opcodes.Phi 236 | 237 | class Copy(Operation): 238 | def __init__(self): 239 | super(Copy, self).__init__(numInputs = 2, numOutputs = 0, numTempvars = 0) 240 | self.opcode = opcodes.opcodes.Copy 241 | 242 | class BeginFunction(Operation): 243 | def __init__(self,signature): 244 | super(BeginFunction, self).__init__(numInputs = 0, numOutputs = 1, numTempvars = signature.numArgs, attributes = [Operation.Attributes.isBlockBegin]) 245 | self.opcode = opcodes.opcodes.BeginFunction 246 | self.signature = signature 247 | 248 | class EndFunction(Operation): 249 | def __init__(self): 250 | super(EndFunction, self).__init__(numInputs=0, numOutputs=0, numTempvars=0, attributes = [Operation.Attributes.isBlockEnd]) 251 | self.opcode = opcodes.opcodes.EndFunction 252 | 253 | 254 | 255 | class ThrowException(Operation): 256 | def __init__(self): 257 | super(ThrowException, self).__init__(numInputs = 1, numOutputs= 0, numTempvars = 0, attributes = []) 258 | self.opcode = opcodes.opcodes.ThrowException 259 | 260 | class BeginTry(Operation): 261 | def __init__(self): 262 | super(BeginTry, self).__init__(numInputs= 0, numOutputs= 0, numTempvars = 0, attributes = [Operation.Attributes.isBlockBegin]) 263 | self.opcode = opcodes.opcodes.BeginTry 264 | 265 | class BeginCatch(Operation): 266 | def __init__(self): 267 | super(BeginCatch, self).__init__(numInputs = 0, numOutputs= 0, numTempvars = 0, attributes = [Operation.Attributes.isBlockBegin, Operation.Attributes.isBlockEnd]) 268 | self.opcode = opcodes.opcodes.BeginCatch 269 | 270 | class EndTryCatch(Operation): 271 | def __init__(self): 272 | super(EndTryCatch, self).__init__(numInputs = 0, numOutputs= 0, numTempvars = 0, attributes = [Operation.Attributes.isBlockEnd]) 273 | self.opcode = opcodes.opcodes.EndTryCatch 274 | 275 | class CreateDict(Operation): 276 | def __init__(self, numInitialValues): 277 | super(CreateDict, self).__init__(numInputs=numInitialValues, numOutputs=1, numTempvars=0) 278 | self.opcode = opcodes.opcodes.CreateDict 279 | 280 | class GetArrayElem(Operation): 281 | def __init__(self): 282 | super(GetArrayElem, self).__init__(numInputs=2, numOutputs=1, numTempvars=0) 283 | self.opcode = opcodes.opcodes.GetArrayElem 284 | 285 | class SetArrayElem(Operation): 286 | def __init__(self): 287 | super(SetArrayElem, self).__init__(numInputs=3, numOutputs=0, numTempvars=0) 288 | self.opcode = opcodes.opcodes.SetArrayElem 289 | 290 | class BeginClass(Operation): 291 | pass 292 | 293 | class EndClass(Operation): 294 | pass 295 | 296 | class BeginForEach(Operation): 297 | pass 298 | 299 | class Print(Operation): 300 | def __init__(self): 301 | super(Print, self).__init__(numInputs = 1, numOutputs= 0, numTempvars = 0, attributes = []) 302 | self.opcode = opcodes.opcodes.Print 303 | 304 | class Comparater: 305 | equal = "==" 306 | strictEqual = "===" 307 | notEqual = "!=" 308 | lessThan = "<" 309 | lessThanOrEqual = "<=" 310 | greaterThan = ">" 311 | greaterThanOrEqual = ">=" 312 | @staticmethod 313 | def all(): 314 | return [Comparater.equal, Comparater.strictEqual, Comparater.notEqual, Comparater.lessThan, Comparater.lessThanOrEqual, Comparater.greaterThan, Comparater.greaterThanOrEqual] 315 | 316 | class UnaryOperator: 317 | Inc = "++" 318 | Dec = "--" 319 | LogicalNot = "!" 320 | BitwiseNot = "~" 321 | 322 | @staticmethod 323 | def all(): 324 | return [UnaryOperator.Inc, UnaryOperator.Dec, UnaryOperator.BitwiseNot, UnaryOperator.LogicalNot] 325 | 326 | 327 | class BinaryOperator: 328 | Add = "+" 329 | Sub = "-" 330 | Mul = "*" 331 | Div = "/" 332 | Mod = "%" 333 | BitAnd = "&" 334 | BitOr = "|" 335 | LogicAnd= "&&" 336 | LogicOr = "||" 337 | Xor = "^" 338 | LShift = "<<" 339 | RShift = ">>" 340 | 341 | @staticmethod 342 | def all(): 343 | return [BinaryOperator.Add, BinaryOperator.Sub, BinaryOperator.Mul, BinaryOperator.Div, BinaryOperator.Mod, BinaryOperator.BitAnd, BinaryOperator.BitOr, BinaryOperator.LogicAnd, BinaryOperator.LogicOr, BinaryOperator.Xor, BinaryOperator.LShift, BinaryOperator.RShift ] 344 | -------------------------------------------------------------------------------- /PhpIL/lifter.py: -------------------------------------------------------------------------------- 1 | import program 2 | import codeEmitter 3 | import instructions 4 | import probability 5 | import operation 6 | import variable 7 | import typesData 8 | from opcodes import opcodes 9 | 10 | class Lifter: 11 | 12 | def __init__(self, prog): 13 | self.program = prog 14 | self.emitter = codeEmitter.CodeEmitter() 15 | 16 | def emit(self, text): 17 | self.emitter.emit(text) 18 | 19 | def emitline(self, text): 20 | self.emitter.emitline(text) 21 | 22 | def getCode(self): 23 | return str(self.emitter) 24 | 25 | def doLifting(self): 26 | for i in self.program.instructionList: 27 | self.lift(i) 28 | 29 | def lift(self,inst): 30 | 31 | opcode = inst.getOpcode() 32 | 33 | if opcode == opcodes.LoadInteger or \ 34 | opcode == opcodes.LoadFloat or \ 35 | opcode == opcodes.LoadBoolean: 36 | 37 | self.emitline(str(inst.getOutput()) + " = " + str(inst.operation.value)) 38 | 39 | if opcode == opcodes.LoadString: 40 | self.emitline(str(inst.getOutput()) + " = \"" + str(inst.operation.value)+"\"") 41 | 42 | if opcode == opcodes.Nop: 43 | pass 44 | 45 | if opcode == opcodes.BeginFunction: 46 | output = inst.getOutput() 47 | signature = inst.operation.signature 48 | args = inst.getAllTemps() 49 | 50 | code = str(output) + " = function( " 51 | code += ", ".join([str(x) for x in args]) 52 | code += ") " 53 | 54 | outerVars = signature.getOuterVars() 55 | # print outerVars 56 | if len(outerVars) > 0: 57 | code += "use (" 58 | for var in outerVars: 59 | code += str(var)+", " 60 | if code[-2:] == ', ': 61 | code = code[:-2] 62 | code += " ){" 63 | 64 | self.emit(code) 65 | self.emitter.increaseIndentLevel() 66 | 67 | if opcode == opcodes.EndFunction: 68 | self.emitter.decreaseIndentLevel() 69 | self.emitline("}") 70 | 71 | 72 | if opcode == opcodes.CallFunction: 73 | output = str(inst.getOutput()) 74 | func = inst.getInput() 75 | 76 | code = output + " = " + str(func)+"( " 77 | code += ", ".join([str(x) for x in inst.getAllInputs()[1:]]) 78 | code += ")" 79 | 80 | self.emitline(code) 81 | 82 | 83 | if opcode == opcodes.LoadNull: 84 | self.emitline(str(inst.getOutput()) + " = NULL") 85 | 86 | if opcode == opcodes.Return: 87 | self.emitline("return " + str(inst.getInput())) 88 | 89 | if opcode == opcodes.BeginIf: 90 | self.emit("if(" + str(inst.getInput(0)) + "){") 91 | self.emitter.increaseIndentLevel() 92 | 93 | if opcode == opcodes.BeginElse: 94 | self.emitter.decreaseIndentLevel() 95 | self.emit("}else{") 96 | self.emitter.increaseIndentLevel() 97 | 98 | if opcode == opcodes.EndIf: 99 | self.emitter.decreaseIndentLevel() 100 | self.emit("}") 101 | 102 | if opcode == opcodes.Break: 103 | self.emitline("break") 104 | 105 | if opcode == opcodes.Continue: 106 | self.emitline("continue") 107 | 108 | if opcode == opcodes.UnaryOperation: 109 | code = str(inst.getInput()) + " = " 110 | altCode = str(inst.getOutput()) + " = " 111 | commonCode = "" 112 | op = inst.operation.op 113 | if op == operation.UnaryOperator.Inc: 114 | commonCode = str(inst.getInput())+ " + 1" 115 | if op == operation.UnaryOperator.Dec: 116 | commonCode = str(inst.getInput())+ " - 1" 117 | if op == operation.UnaryOperator.BitwiseNot: 118 | commonCode = str(inst.operation.op) + str(inst.getInput()) 119 | if op == operation.UnaryOperator.LogicalNot: 120 | commonCode = str(inst.operation.op) + str(inst.getInput()) 121 | 122 | code += commonCode 123 | altCode += commonCode 124 | self.emitline(code) 125 | self.emitline(altCode) 126 | 127 | if opcode == opcodes.BinaryOperation: 128 | out = str(inst.getOutput()) 129 | inp1 = str(inst.getInput(0)) 130 | inp2 = str(inst.getInput(1)) 131 | 132 | op = inst.operation.op 133 | if(op == operation.BinaryOperator.LShift or op == operation.BinaryOperator.RShift): 134 | code = inp1 + str(inst.operation.op) + inp2 135 | code = "if("+inp2+">0){"+ out + " = " + code + ";" +"}" 136 | self.emit(code) 137 | else: 138 | code = inp1 + str(inst.operation.op) + inp2 139 | self.emitline(out+" = " + code) 140 | 141 | 142 | if opcode == opcodes.BeginFor: 143 | loopvar = inst.getTemp() 144 | start = inst.getInput(0) 145 | end = inst.getInput(1) 146 | step = inst.getInput(2) 147 | 148 | code = "for(" 149 | code += str(loopvar) + " = " + str(start) + "; " 150 | code += str(loopvar) + " < " + str(end) + " ; " 151 | code += str(loopvar) + " = " + str(loopvar) + " + " + str(step) 152 | 153 | self.emit(code + "){") 154 | self.emitter.increaseIndentLevel() 155 | 156 | 157 | if opcode == opcodes.EndFor: 158 | self.emitter.decreaseIndentLevel() 159 | self.emit("}") 160 | 161 | if opcode == opcodes.BeginWhile: 162 | inp = str(inst.getInput(0)) + str(inst.operation.comparater) + str(inst.getInput(1)) 163 | self.emit("while (" + inp + "){") 164 | self.emitter.increaseIndentLevel() 165 | 166 | if opcode == opcodes.EndWhile: 167 | self.emitter.decreaseIndentLevel() 168 | self.emit("}") 169 | 170 | if opcode == opcodes.BeginDoWhile: 171 | self.emit("do{") 172 | self.emitter.increaseIndentLevel() 173 | 174 | if opcode == opcodes.EndDoWhile: 175 | self.emitter.decreaseIndentLevel() 176 | inp = str(inst.getInput(0)) + str(inst.operation.comparater) + str(inst.getInput(1)) 177 | self.emitline("}while(" + inp + ")") 178 | 179 | 180 | if opcode == opcodes.Include: 181 | self.emitline("include "+str(inst.getInput())) 182 | 183 | if opcode == opcodes.Copy: 184 | inp1 = str(inst.getInput(0)) 185 | inp2 = str(inst.getInput(1)) 186 | self.emitline(inp1 + " = " + inp2) 187 | 188 | if opcode == opcodes.Phi: 189 | out = str(inst.getOutput()) 190 | inp = str(inst.getInput()) 191 | self.emitline(out + " = " + inp) 192 | 193 | if opcode == opcodes.BeginTry: 194 | self.emit("try{") 195 | self.emitter.increaseIndentLevel() 196 | 197 | if opcode == opcodes.BeginCatch: 198 | self.emitter.decreaseIndentLevel() 199 | self.emit("}catch(Exception $e){") 200 | self.emitter.increaseIndentLevel() 201 | 202 | if opcode == opcodes.EndTryCatch: 203 | self.emitter.decreaseIndentLevel() 204 | self.emit("}") 205 | 206 | if opcode == opcodes.CreateArray: 207 | code = str(inst.getOutput()) + " = " 208 | if probability.Random.probability(0.5): 209 | code += "[" + ", ".join([str(x) for x in inst.getAllInputs()]) + "]" 210 | else: 211 | code += "Array (" + ", ".join([str(x) for x in inst.getAllInputs()]) + ")" 212 | 213 | self.emitline(code) 214 | 215 | if opcode == opcodes.CreateDict: 216 | code = str(inst.getOutput()) + " = " 217 | if probability.Random.probability(0.5): 218 | code += "[" 219 | for key, value in inst.getAllInputs(): 220 | code += str(key) + " => " + str(value) + ", " 221 | if code[-2:] == ", ": 222 | code = code[:-2] 223 | code += "]" 224 | else: 225 | code += "Array(" 226 | for key, value in inst.getAllInputs(): 227 | code += str(key) + " => " + str(value) + ", " 228 | if code[-2:] == ", ": 229 | code = code[:-2] 230 | code += ")" 231 | 232 | self.emitline(code) 233 | 234 | if opcode == opcodes.GetArrayElem: 235 | code = str(inst.getOutput()) + " = " 236 | code += str(inst.getInput(0)) + "[" + str(inst.getInput(1)) + "]" 237 | self.emitline(code) 238 | 239 | if opcode == opcodes.SetArrayElem: 240 | code = str(inst.getInput(0)) + "[" + str(inst.getInput(1)) + "]" 241 | code += " = " + str(inst.getInput(2)) 242 | self.emitline(code) 243 | 244 | 245 | if __name__ == '__main__': 246 | def main(): 247 | prog = program.Program([ 248 | instructions.Instruction(operation.LoadInteger(10),False,[variable.Variable(0)]), 249 | instructions.Instruction(operation.LoadFloat(1.1),False,[variable.Variable(1)]), 250 | instructions.Instruction(operation.LoadBoolean(True),False,[variable.Variable(1)]), 251 | instructions.Instruction(operation.LoadString("qweqweqweqwe"),False,[variable.Variable(0)]), 252 | instructions.Instruction(operation.BeginIf(),[variable.Variable(2)]), 253 | instructions.Instruction(operation.BeginElse()), 254 | instructions.Instruction(operation.EndIf()) 255 | 256 | ]) 257 | 258 | prog = program.Program([ 259 | instructions.Instruction(operation.LoadString("phar"),False,[variable.Variable(100)]), 260 | instructions.Instruction(operation.Include(),[variable.Variable(100)]), 261 | instructions.Instruction(operation.Include(),[variable.Variable(100)]), 262 | 263 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(0)]), 264 | instructions.Instruction(operation.BeginFunction(typesData.FunctionSignature(2)),False,[variable.Variable(1)],[variable.Variable(10),variable.Variable(11)]), 265 | instructions.Instruction(operation.BinaryOperation("+"),[variable.Variable(10),variable.Variable(11)],[variable.Variable(2)]), 266 | instructions.Instruction(operation.LoadString("somestring"),False,[variable.Variable(3)]), 267 | instructions.Instruction(operation.Return(),[variable.Variable(2)]), 268 | instructions.Instruction(operation.EndFunction()), 269 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(4)]), 270 | instructions.Instruction(operation.CallFunction(2),[variable.Variable(1), variable.Variable(4), variable.Variable(0)],[variable.Variable(6)]), 271 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(7)]), 272 | instructions.Instruction(operation.Break()), 273 | instructions.Instruction(operation.Continue()), 274 | instructions.Instruction(operation.UnaryOperation("++"),[variable.Variable(0)],[variable.Variable(0)]), 275 | ]) 276 | 277 | 278 | prog = program.Program([ 279 | instructions.Instruction(operation.LoadString("phar"),False,[variable.Variable(100)]), 280 | instructions.Instruction(operation.Include(),[variable.Variable(100)]), 281 | instructions.Instruction(operation.Include(),[variable.Variable(100)]), 282 | 283 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(0)]), 284 | instructions.Instruction(operation.LoadInteger(1), False, [variable.Variable(1)]), 285 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(2)]), 286 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(3)]), 287 | instructions.Instruction(operation.LoadInteger(20), False, [variable.Variable(4)]), 288 | instructions.Instruction(operation.LoadInteger(5), False, [variable.Variable(5)]), 289 | instructions.Instruction(operation.LoadInteger(50), False, [variable.Variable(8)]), 290 | instructions.Instruction(operation.Phi(), [variable.Variable(3)], [variable.Variable(6)]), 291 | instructions.Instruction(operation.Phi(), [variable.Variable(4)], [variable.Variable(7)]), 292 | instructions.Instruction(operation.BeginFor("++", "<"), [variable.Variable(0),variable.Variable(2),variable.Variable(8)], False, [variable.Variable(80)]), 293 | instructions.Instruction(operation.BinaryOperation("<"), [variable.Variable(8), variable.Variable(5)], [variable.Variable(6)]), 294 | instructions.Instruction(operation.BeginIf(), [variable.Variable(6)], False), 295 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 296 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 297 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(6), variable.Variable(1)], [variable.Variable(10)]), 298 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 299 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 300 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 301 | instructions.Instruction(operation.EndWhile(), False, False), 302 | 303 | instructions.Instruction(operation.BeginElse(), False, False), 304 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 305 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 306 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(7), variable.Variable(1)], [variable.Variable(10)]), 307 | instructions.Instruction(operation.Copy(), [variable.Variable(7), variable.Variable(10)]), 308 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 309 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 310 | instructions.Instruction(operation.EndWhile(), False, False), 311 | 312 | instructions.Instruction(operation.EndIf(), False, False), 313 | instructions.Instruction(operation.EndFor(), False, False), 314 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(90)]), 315 | ]) 316 | # print prog 317 | l = Lifter(prog) 318 | l.doLifting() 319 | print l.emitter 320 | main() 321 | -------------------------------------------------------------------------------- /PhpIL/analyzer.py: -------------------------------------------------------------------------------- 1 | import program 2 | import opcodes 3 | import variable 4 | import operation 5 | import instructions 6 | from typesData import Types 7 | 8 | class Analyzer(object): 9 | 10 | def __init__(self, programToAnalyse): 11 | self.program = programToAnalyse 12 | 13 | ''' Perform analysis on the entire program''' 14 | def doAnalyze(self): 15 | for inst in self.program.instructionList: 16 | self.analyze(inst) 17 | 18 | ''' Virtual function that analyzes a given instruction ''' 19 | def analyze(self,inst): 20 | pass 21 | 22 | class ScopeAnalyzer(Analyzer): 23 | 24 | def __init__(self, programToAnalyse): 25 | super(ScopeAnalyzer, self).__init__(programToAnalyse) 26 | self.scopes = [set([])] 27 | self.numScopes = 1 28 | self.stack = [] 29 | 30 | def getVisibleVars(self): 31 | # print [j for i in self.scopes for j in i] 32 | return [j for i in self.scopes for j in i] 33 | 34 | def getOuterVisibleVars(self): 35 | outerScopes = self.scopes[:-1] 36 | # print self.scopes 37 | return [j for i in outerScopes for j in i] 38 | 39 | def analyze(self, inst): 40 | # print self.scopes 41 | 42 | if inst.isBlockEnd(): 43 | self.scopes.pop() 44 | if inst.getOpcode() == operation.EndFunction: 45 | out = self.stack.pop() 46 | self.scopes[-1].update([out]) 47 | 48 | if inst.getOpcode() == opcodes.opcodes.BeginFunction: 49 | self.stack.append(inst.getOutput()) 50 | else: 51 | self.scopes[-1].update(inst.getAllOutputs()) 52 | 53 | if inst.isBlockBegin(): 54 | self.scopes.append(set([])) 55 | 56 | self.scopes[-1].update(inst.getAllTemps()) 57 | 58 | # print self.scopes 59 | 60 | class ContextAnalyzer(Analyzer): 61 | 62 | isGlobal = 0 63 | isInLoop = 1 << 0 64 | isInFunction = 1 << 1 65 | 66 | def __init__(self,programToAnalyse): 67 | super(ContextAnalyzer, self).__init__(programToAnalyse) 68 | self.context = [[0]] 69 | self.lastContext = [[0]] 70 | 71 | def analyze(self, inst): 72 | 73 | def debug(): 74 | a=[self.context] 75 | if self.context[-1][0] == 0: 76 | a.append("Global") 77 | 78 | if self.context[-1][0] & ContextAnalyzer.isInLoop: 79 | a.append("InLoop") 80 | 81 | if self.context[-1][0] & ContextAnalyzer.isInFunction: 82 | a.append("InFunction") 83 | print a 84 | 85 | if inst.isLoopBegin() or inst.isBeginFunction(): 86 | self.context.append([self.context[-1][0]]) 87 | self.lastContext.append([]) 88 | 89 | if inst.isBeginFunction(): 90 | self.context[-1][0] |= ContextAnalyzer.isInFunction 91 | self.lastContext[-1].append(ContextAnalyzer.isInFunction) 92 | 93 | if inst.isEndFunction(): 94 | self.context[-1][0] &= ~ContextAnalyzer.isInFunction 95 | 96 | if inst.isLoopBegin(): 97 | self.context[-1][0] |= ContextAnalyzer.isInLoop 98 | self.lastContext[-1].append(ContextAnalyzer.isInLoop) 99 | 100 | if inst.isLoopEnd(): 101 | self.context[-1][0] &= ~ContextAnalyzer.isInLoop 102 | 103 | if inst.isEndFunction() or inst.isLoopEnd(): 104 | self.context.pop() 105 | self.lastContext.pop() 106 | 107 | # debug() 108 | 109 | def isGlobalContext(self): 110 | return self.context[-1][0] == 0 111 | 112 | def isInLoopContext(self): 113 | return self.context[-1][0] & ContextAnalyzer.isInLoop 114 | 115 | def isInFunctionContext(self): 116 | return self.context[-1][0] & ContextAnalyzer.isInFunction 117 | 118 | def lastContextisLoop(self): 119 | return self.lastContext[-1][0] == ContextAnalyzer.isInLoop 120 | 121 | 122 | class TypeAnalyzer(Analyzer): 123 | 124 | def __init__(self, programToAnalyze): 125 | super(TypeAnalyzer, self).__init__(programToAnalyze) 126 | self.variableTypes = [{}] 127 | self.stack = [] 128 | self.returnStack = [] 129 | self.signatureTracker = {} 130 | 131 | def setType(self, vars, type): 132 | for i in vars: 133 | self.variableTypes[-1][i] = type 134 | 135 | def getType(self, var): 136 | for i in self.variableTypes: 137 | if var in i: 138 | return i[var] 139 | 140 | def getSignature(self, var): 141 | if self.getType(var) == Types.Function: 142 | return self.signatureTracker[var] 143 | return False 144 | 145 | def analyze(self, inst): 146 | 147 | if inst.getOpcode() == opcodes.opcodes.LoadInteger: 148 | self.setType(inst.getAllOutputs(), Types.Integer) 149 | if inst.getOpcode() == opcodes.opcodes.LoadFloat: 150 | self.setType(inst.getAllOutputs(), Types.Float) 151 | if inst.getOpcode() == opcodes.opcodes.LoadString: 152 | self.setType(inst.getAllOutputs(), Types.String) 153 | if inst.getOpcode() == opcodes.opcodes.LoadBoolean: 154 | self.setType(inst.getAllOutputs(), Types.Boolean) 155 | if inst.getOpcode() == opcodes.opcodes.LoadNull: 156 | self.setType(inst.getAllOutputs(), Types.Null) 157 | # if inst.getOpcode() == opcodes.opcodes.LoadObject: 158 | # self.setType(inst.getAllOutputs(), Types.Object) 159 | if inst.getOpcode() == opcodes.opcodes.BeginClass: 160 | self.setType(inst.getAllOutputs(), Types.Class) 161 | 162 | if inst.getOpcode() == opcodes.opcodes.UnaryOperation: 163 | if self.getType(inst.getInput()) == Types.Unknown: 164 | self.setType(inst.getAllInputs(), Types.Integer) 165 | self.setType(inst.getAllOutputs(), self.getType(inst.getInput(0))) 166 | 167 | if inst.getOpcode() == opcodes.opcodes.BeginFor: 168 | self.setType(inst.getAllTemps(), self.getType(Types.Unknown)) 169 | 170 | if inst.getOpcode() == opcodes.opcodes.BinaryOperation: 171 | 172 | op = inst.operation.op 173 | 174 | if op == operation.Comparater.equal or \ 175 | op == operation.Comparater.notEqual or \ 176 | op == operation.Comparater.greaterThan or \ 177 | op == operation.Comparater.greaterThanOrEqual or \ 178 | op == operation.Comparater.lessThan or \ 179 | op == operation.Comparater.lessThanOrEqual or \ 180 | op == operation.Comparater.strictEqual or \ 181 | op == operation.BinaryOperator.LogicOr or \ 182 | op == operation.BinaryOperator.LogicAnd: 183 | 184 | self.setType(inst.getAllOutputs(),Types.Boolean) 185 | 186 | if op == operation.BinaryOperator.Add or \ 187 | op == operation.BinaryOperator.Sub or \ 188 | op == operation.BinaryOperator.Mul or \ 189 | op == operation.BinaryOperator.Div or \ 190 | op == operation.BinaryOperator.LShift or \ 191 | op == operation.BinaryOperator.RShift: 192 | 193 | outType = Types.Integer 194 | inps = inst.getAllInputs() 195 | if self.getType(inps[0]) == Types.Float or self.getType(inps[1]) == Types.Float: 196 | outType = Types.Float 197 | self.setType(inst.getAllOutputs(),outType) 198 | 199 | if op == operation.BinaryOperator.BitOr or \ 200 | op == operation.BinaryOperator.BitAnd or \ 201 | op == operation.BinaryOperator.Xor: 202 | 203 | outType = Types.Integer 204 | inps = inst.getAllInputs() 205 | if self.getType(inps[0]) == Types.String or self.getType(inps[1]) == Types.String: 206 | outType = Types.String 207 | self.setType(inst.getAllOutputs(),outType) 208 | 209 | if op == operation.BinaryOperator.Mod: 210 | 211 | self.setType(inst.getAllOutputs(),Types.Integer) 212 | 213 | if inst.getOpcode() == opcodes.opcodes.Phi: 214 | inp = inst.getInput() 215 | self.setType(inst.getAllOutputs(), self.getType(inp)) 216 | if self.getType(inp) == Types.Function: 217 | self.signatureTracker[inst.getOutput()] = self.getSignature(inp) 218 | 219 | if inst.getOpcode() == opcodes.opcodes.Copy: 220 | inp = inst.getInput(1) 221 | self.setType([inst.getInput(0)], self.getType(inp)) 222 | if self.getType(inp) == Types.Function: 223 | self.signatureTracker[inst.getInput(0)] = self.getSignature(inp) 224 | 225 | if inst.isBeginFunction(): 226 | self.setType(inst.getAllOutputs(), Types.Function) 227 | self.setType(inst.getAllTemps(), Types.Unknown) 228 | self.stack.append(inst) 229 | self.variableTypes.append({}) 230 | self.returnStack.append([]) 231 | self.signatureTracker[inst.getOutput()] = inst.operation.signature 232 | 233 | if inst.isEndFunction(): 234 | stackFrame = self.variableTypes.pop() 235 | returnType = self.returnStack.pop()[0] 236 | func = self.stack.pop() 237 | signature = func.operation.signature 238 | outputVar = func.getOutput() 239 | inputTypes = [self.getType(var) for var in func.getAllTemps()] 240 | 241 | signature.isCons = False 242 | signature.setReturnType(returnType) 243 | signature.setInputTypes(inputTypes) 244 | 245 | if inst.getOpcode() == opcodes.opcodes.Return: 246 | self.returnStack[-1].append(self.getType(inst.getInput(0))) 247 | 248 | if inst.getOpcode() == opcodes.opcodes.CallFunction: 249 | func = self.signatureTracker[inst.getInput()] 250 | returnType = func.getReturnType() 251 | self.setType(inst.getAllOutputs(), returnType) 252 | 253 | if inst.getOpcode() == opcodes.opcodes.BeginIf: 254 | if self.getType(inst.getInput()) == Types.Unknown: 255 | self.setType(inst.getAllInputs(), Types.Boolean) 256 | 257 | if inst.getOpcode() == opcodes.opcodes.CreateArray: 258 | self.setType(inst.getAllOutputs(), Types.Array) 259 | 260 | 261 | # print self.variableTypes 262 | 263 | 264 | 265 | # Tests -> 266 | 267 | if __name__ == '__main__': 268 | import typesData 269 | def main(): 270 | prog = program.Program([ 271 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(0)]), 272 | instructions.Instruction(operation.LoadInteger(9),False,[variable.Variable(3)]), 273 | instructions.Instruction(operation.LoadString("thisisastring"),False,[variable.Variable(1)]), 274 | instructions.Instruction(operation.LoadInteger(True),False,[variable.Variable(4)]), 275 | instructions.Instruction(operation.BeginWhile(">"),[variable.Variable(0), variable.Variable(3)]), 276 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(6)]), 277 | instructions.Instruction(operation.BeginIf(),[variable.Variable(2)]), 278 | instructions.Instruction(operation.LoadString("thisisastring"),False,[variable.Variable(9)]), 279 | instructions.Instruction(operation.EndIf()), 280 | instructions.Instruction(operation.BinaryOperation(">"),[variable.Variable(0),variable.Variable(3)],[variable.Variable(5)]), 281 | instructions.Instruction(operation.EndWhile()), 282 | instructions.Instruction(operation.LoadInteger(10),False,[variable.Variable(31337)]), 283 | ]) 284 | prog = program.Program([ 285 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(0)]), 286 | instructions.Instruction(operation.LoadInteger(1), False, [variable.Variable(1)]), 287 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(2)]), 288 | instructions.Instruction(operation.LoadInteger(10), False, [variable.Variable(3)]), 289 | instructions.Instruction(operation.LoadInteger(20), False, [variable.Variable(4)]), 290 | instructions.Instruction(operation.LoadInteger(5), False, [variable.Variable(5)]), 291 | instructions.Instruction(operation.Phi(), [variable.Variable(3)], [variable.Variable(6)]), 292 | instructions.Instruction(operation.Phi(), [variable.Variable(4)], [variable.Variable(7)]), 293 | instructions.Instruction(operation.BeginFor("++", "<"), [variable.Variable(0),variable.Variable(2),variable.Variable(8)]), 294 | instructions.Instruction(operation.BinaryOperation("<"), [variable.Variable(8), variable.Variable(5)], [variable.Variable(6)]), 295 | instructions.Instruction(operation.BeginIf(), [variable.Variable(6)], False), 296 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 297 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 298 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(6), variable.Variable(1)], [variable.Variable(10)]), 299 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 300 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 301 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 302 | 303 | instructions.Instruction(operation.BeginFunction(typesData.FunctionSignature(2,[variable.Variable(11)])),False,[variable.Variable(1)],[variable.Variable(10),variable.Variable(11)]), 304 | instructions.Instruction(operation.BinaryOperation("+"),[variable.Variable(10),variable.Variable(11)],[variable.Variable(2)]), 305 | instructions.Instruction(operation.LoadString("somestring"),False,[variable.Variable(3)]), 306 | instructions.Instruction(operation.Return(),[variable.Variable(2)]), 307 | instructions.Instruction(operation.EndFunction()), 308 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(4)]), 309 | instructions.Instruction(operation.CallFunction(2),[variable.Variable(1), variable.Variable(4), variable.Variable(0)],[variable.Variable(6)]), 310 | 311 | instructions.Instruction(operation.EndWhile(), False, False), 312 | 313 | instructions.Instruction(operation.BeginElse(), False, False), 314 | instructions.Instruction(operation.LoadInteger(0), False, [variable.Variable(9)]), 315 | instructions.Instruction(operation.BeginWhile("<"),[variable.Variable(9), variable.Variable(5)], False ), 316 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(7), variable.Variable(1)], [variable.Variable(10)]), 317 | instructions.Instruction(operation.Copy(), [variable.Variable(7), variable.Variable(10)]), 318 | instructions.Instruction(operation.BinaryOperation("+"), [variable.Variable(9), variable.Variable(1)], [variable.Variable(11)]), 319 | instructions.Instruction(operation.Copy(), [variable.Variable(6), variable.Variable(10)]), 320 | instructions.Instruction(operation.EndWhile(), False, False), 321 | 322 | instructions.Instruction(operation.EndIf(), False, False), 323 | instructions.Instruction(operation.EndFor(), False, False), 324 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(90)]), 325 | ]) 326 | program.Program([ 327 | instructions.Instruction(operation.LoadInteger(1),False,[variable.Variable(0)]), 328 | instructions.Instruction(operation.BeginFunction(typesData.FunctionSignature(2,[variable.Variable(11)])),False,[variable.Variable(1)],[variable.Variable(10),variable.Variable(11)]), 329 | instructions.Instruction(operation.BinaryOperation("+"),[variable.Variable(10),variable.Variable(11)],[variable.Variable(2)]), 330 | instructions.Instruction(operation.LoadString("somestring"),False,[variable.Variable(3)]), 331 | instructions.Instruction(operation.Return(),[variable.Variable(2)]), 332 | instructions.Instruction(operation.EndFunction()), 333 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(4)]), 334 | instructions.Instruction(operation.CallFunction(2),[variable.Variable(1), variable.Variable(4), variable.Variable(0)],[variable.Variable(6)]), 335 | instructions.Instruction(operation.LoadInteger(1337),False,[variable.Variable(7)]), 336 | ]) 337 | print prog 338 | ctx = ContextAnalyzer(prog) 339 | ctx.doAnalyze() 340 | # 341 | # sc = ScopeAnalyzer(prog) 342 | # sc.doAnalyze() 343 | 344 | 345 | # ti = TypeAnalyzer(prog) 346 | # ti.doAnalyze() 347 | 348 | 349 | main() 350 | --------------------------------------------------------------------------------