def generateBinaryExp(operator, lnode, rnode): node = TreeNode('BinaryOperation') node.attributes = {} node.attributes['operator'] = operator node.children.append(lnode) node.children.append(rnode) return node
def repair_unmatched_type(ast, charno): for num in charno: try: defectNode = BFSGetNode(ast, num) decNode = None nodeQ = Queue() nodeQ.put(defectNode) # root while (not nodeQ.empty()): tmpNode = nodeQ.get() if tmpNode.nodeType == 'VariableDeclaration': decNode = tmpNode break for childNode in tmpNode.children: nodeQ.put(childNode) if len(decNode.children) > 0: oriType = decNode.children[0].attributes['name'] curType = oriType.translate(str.maketrans('', '', digits)) decNode.children[0].attributes['name'] = curType decNode.children[0].attributes['type'] = curType else: # handle the var typeNode = TreeNode('ElementaryTypeName') typeNode.attributes = {} typeNode.attributes['name'] = 'uint' typeNode.attributes['type'] = 'uint' decNode.children.append(typeNode) except: print('failing to repair the unmatched type defect in charnum:' + str(num)) continue
def generateRequire(): node = TreeNode('FunctionCall') identifierNode = TreeNode('Identifier') identifierNode.attributes = {} identifierNode.attributes['value'] = 'require' node.children.append(identifierNode) return node
def repair_misleading_dataloc(ast, charno): for num in charno: try: defectNode = BFSGetNode(ast, num) funcCallNode = TreeNode('FunctionCall') newNode = TreeNode('NewExpression') idenNode = defectNode.children[0].children[0] newNode.children.append(idenNode) funcCallNode.children.append(newNode) defectNode.children.append(funcCallNode) except: print('failing to repair the misleading defect in charnum:' + str(num)) continue
def generateJudgeZero(rnode): node = TreeNode('IfStatement') zeroNode = TreeNode('Literal') zeroNode.attributes = {} zeroNode.attributes['value'] = '0' zeroNode.attributes['token'] = 'number' binaryNode = generateBinaryExp('!=', rnode, zeroNode) node.children.append(binaryNode) return node
def add_require_protect(defectNode): # find the contract node contractNode = defectNode while contractNode.nodeType != 'ContractDefinition': contractNode = contractNode.father state_var = [] for item in contractNode.children: if item.nodeType == 'VariableDeclaration': if len(item.children) > 0 and item.children[0].nodeType == 'ElementaryTypeName' and item.children[0].attributes['name'] == 'address': state_var.append(item.attributes['name']) owner_var = '' for var in state_var: if 'owner' in var or 'create' in var or 'admin' in var: owner_var = var break if owner_var == '' and len(state_var) > 0: owner_var = state_var[0] if len(state_var) == 0: # add a variable declaration and insert into constructor owner_idennode = TreeNode('VariableDeclaration') owner_idennode.attributes = {'name':'contractOwner'} ele_node = TreeNode('ElementaryTypeName') ele_node.attributes = {'name':'address', 'value':'address'} owner_idennode.children.append(ele_node) idx = 0 while idx < len(contractNode.children): if contractNode.children[idx].nodeType != 'InheritanceSpecifier': break idx+=1 constructorNode = '' for child in contractNode.children: if child.nodeType == 'FunctionDefinition' and child.attributes['isConstructor'] == True: constructorNode = child break param_node = copy.deepcopy(owner_idennode) param_node.attributes['name'] = '_owner' # constructorNode.children[0].children.append(param_node) for ele in constructorNode.children: if ele.nodeType == 'ParameterList': ele.children.append(param_node) break expNode = TreeNode('ExpressionStatement') curbinaryOpNode = TreeNode('BinaryOperation') curbinaryOpNode.attributes = {} curbinaryOpNode.attributes['operator'] = '=' left_node = TreeNode('Identifier') left_node.attributes = {'value':'contractOwner'} right_node = TreeNode('Identifier') right_node.attributes = {'value':'_owner'} curbinaryOpNode.children.append(left_node) curbinaryOpNode.children.append(right_node) expNode.children.append(curbinaryOpNode) # constructorNode.children[2].children.insert(0, expNode) for ele in constructorNode.children: if ele.nodeType == 'Block': ele.children.append(expNode) break contractNode.children.insert(idx, owner_idennode) owner_var = 'contractOwner' # add a require(xxx == msg.sender) fatherNode = defectNode.father idx = fatherNode.children.index(defectNode) # msg.sender memaccNode = TreeNode('MemberAccess') memaccNode.attributes = {} memaccNode.attributes['member_name'] = 'sender' idenNode = TreeNode('Identifier') idenNode.attributes = {} idenNode.attributes['value'] = 'msg' memaccNode.children.append(idenNode) reqexpNode = TreeNode('ExpressionStatement') requireNode = TreeNode('FunctionCall') nameNode = TreeNode('Identifier') nameNode.attributes = {} nameNode.attributes['value'] = 'require' binaryOpNode = TreeNode('BinaryOperation') binaryOpNode.beginPoint = -1 binaryOpNode.attributes = {} binaryOpNode.attributes['operator'] = '==' userdefNode = TreeNode('Identifier') userdefNode.attributes = {} userdefNode.attributes['value'] = owner_var binaryOpNode.children.append(userdefNode) binaryOpNode.children.append(memaccNode) requireNode.children.append(nameNode) requireNode.children.append(binaryOpNode) reqexpNode.children.append(requireNode) fatherNode.children.insert(idx, reqexpNode)
def repair_strict_balance(ast, charno): for num in charno: try: defectNode = BFSGetNode(ast, num) # find this.balance thisNode = None nodeQ = Queue() nodeQ.put(defectNode) # root while (not nodeQ.empty()): tmpNode = nodeQ.get() if 'value' in tmpNode.attributes.keys( ) and tmpNode.attributes['value'] == 'this': thisNode = tmpNode for childNode in tmpNode.children: nodeQ.put(childNode) binaryOpNode = thisNode.father.father binaryOpNode1 = copy.deepcopy(binaryOpNode) binaryOpNode2 = copy.deepcopy(binaryOpNode) # >= binaryOpNode1.attributes['operator'] = '>=' binaryOpNode2.attributes['operator'] = '<' origvalNode = binaryOpNode2.children[ 1] # maybe behind is an expression tmpBinaryNode = TreeNode('BinaryOperation') tmpBinaryNode.beginPoint = -1 tmpBinaryNode.attributes = {} tmpBinaryNode.attributes['operator'] = '+' oneNode = TreeNode('Literal') oneNode.attributes = {} oneNode.attributes['value'] = '1' oneNode.attributes['token'] = 'number' tmpBinaryNode.children.append(origvalNode) tmpBinaryNode.children.append(oneNode) secTuple = TreeNode('TupleExpression') secTuple.attributes = {'isInlineArray': False} secTuple.children.append(tmpBinaryNode) binaryOpNode2.children[1] = secTuple binaryOpNodeTotal = TreeNode('BinaryOperation') binaryOpNodeTotal.attributes = {} binaryOpNodeTotal.attributes['operator'] = '&&' tupleNode1 = TreeNode('TupleExpression') tupleNode1.attributes = {'isInlineArray': False} tupleNode1.children.append(binaryOpNode1) tupleNode2 = TreeNode('TupleExpression') tupleNode2.attributes = {'isInlineArray': False} tupleNode2.children.append(binaryOpNode2) binaryOpNodeTotal.children.append(tupleNode1) binaryOpNodeTotal.children.append(tupleNode2) upNode = binaryOpNode.father idx = upNode.children.index(binaryOpNode) upNode.children[idx] = binaryOpNodeTotal except: print('failing to repair the strict balance defect in charnum:' + str(num)) continue
def repair_missing_interrupter(ast, charno): for num in charno: try: defectNode = BFSGetNode(ast, num) if defectNode.nodeType != 'ContractDefinition': # the line is line 1 defectNode = defectNode.children[0] contractNode = defectNode state_var = [] for item in contractNode.children: if item.nodeType == 'VariableDeclaration': if len(item.children) > 0 and item.children[0].nodeType == 'ElementaryTypeName' and item.children[0].attributes['name'] == 'address': state_var.append(item.attributes['name']) owner_var = '' for var in state_var: if 'owner' in var or 'create' in var or 'admin' in var: owner_var = var break if owner_var == '' and len(state_var) > 0: owner_var = state_var[0] if len(state_var) == 0: # add a variable declaration and insert into constructor owner_idennode = TreeNode('VariableDeclaration') owner_idennode.attributes = {'name':'contractOwner'} ele_node = TreeNode('ElementaryTypeName') ele_node.attributes = {'name':'address', 'value':'address'} owner_idennode.children.append(ele_node) idx = 0 while idx < len(contractNode.children): if contractNode.children[idx].nodeType != 'InheritanceSpecifier': break idx+=1 constructorNode = '' for child in contractNode.children: if child.nodeType == 'FunctionDefinition' and child.attributes['isConstructor'] == True: constructorNode = child break param_node = copy.deepcopy(owner_idennode) param_node.attributes['name'] = '_owner' for ele in constructorNode.children: if ele.nodeType == 'ParameterList': ele.children.append(param_node) break expNode = TreeNode('ExpressionStatement') curbinaryOpNode = TreeNode('BinaryOperation') curbinaryOpNode.attributes = {} curbinaryOpNode.attributes['operator'] = '=' left_node = TreeNode('Identifier') left_node.attributes = {'value':'contractOwner'} right_node = TreeNode('Identifier') right_node.attributes = {'value':'_owner'} curbinaryOpNode.children.append(left_node) curbinaryOpNode.children.append(right_node) expNode.children.append(curbinaryOpNode) for ele in constructorNode.children: if ele.nodeType == 'Block': ele.children.append(expNode) break contractNode.children.insert(idx, owner_idennode) owner_var = 'contractOwner' funcDefNode = TreeNode('FunctionDefinition') funcDefNode.attributes = {} funcDefNode.attributes['name'] = 'suicideFunc' funcDefNode.attributes['isConstructor'] = False funcDefNode.attributes['constant'] = False funcDefNode.attributes['visibility'] = 'public' funcDefNode.attributes['stateMutability'] = 'nonpayable' paramNode = TreeNode('ParameterList') returnParamNode = TreeNode('ParameterList') funcDefNode.children.append(paramNode) funcDefNode.children.append(returnParamNode) # msg.sender memaccNode = TreeNode('MemberAccess') memaccNode.attributes = {} memaccNode.attributes['member_name'] = 'sender' idenNode = TreeNode('Identifier') idenNode.attributes = {} idenNode.attributes['value'] = 'msg' memaccNode.children.append(idenNode) # require reqexpNode = TreeNode('ExpressionStatement') requireNode = TreeNode('FunctionCall') nameNode = TreeNode('Identifier') nameNode.attributes = {} nameNode.attributes['value'] = 'require' binaryOpNode = TreeNode('BinaryOperation') binaryOpNode.attributes = {} binaryOpNode.attributes['operator'] = '==' userdefNode = TreeNode('Identifier') userdefNode.attributes = {} userdefNode.attributes['value'] = owner_var binaryOpNode.children.append(userdefNode) binaryOpNode.children.append(memaccNode) requireNode.children.append(nameNode) requireNode.children.append(binaryOpNode) reqexpNode.children.append(requireNode) # selfdestruct blockNode = TreeNode('Block') expNode = TreeNode('ExpressionStatement') funcCallNode = TreeNode('FunctionCall') funcNameNode = TreeNode('Identifier') funcNameNode.attributes = {} funcNameNode.attributes['value'] = 'selfdestruct' funcCallNode.children.append(funcNameNode) funcCallNode.children.append(memaccNode) expNode.children.append(funcCallNode) blockNode.children.append(reqexpNode) blockNode.children.append(expNode) funcDefNode.children.append(blockNode) defectNode.children.append(funcDefNode) except: print('failing to repair the missing interrupt defect in charnum:' + str(num)) continue
def repair_first_type(ast, operator, assign): lNode = assign.children[0] rNode = assign.children[1] requireNode = generateRequire() binaryNode = generateBinaryExp('>=', lNode, rNode) expStatementNode = generateExpStatement() requireNode.children.append(binaryNode) expStatementNode.children.append(requireNode) opStatementNode = assign.father orgBlockNode = opStatementNode.father idx = orgBlockNode.children.index(opStatementNode) if operator == '+=': orgBlockNode.children.insert(idx + 1, expStatementNode) elif operator == '-=': orgBlockNode.children.insert(idx, expStatementNode) elif operator == '*=': # generate a statement: uint tmp = ? tmpVarNode = TreeNode('VariableDeclarationStatement') leftNode = TreeNode('VariableDeclaration') leftNode.attributes = {'name': 'tmp'} eletypeNode = TreeNode('ElementaryTypeName') eletypeNode.attributes = {'name': 'uint'} leftNode.children.append(eletypeNode) rightNode = TreeNode('Identifier') rightNode.attributes = {'value': lNode.attributes['value']} tmpVarNode.children.append(leftNode) tmpVarNode.children.append(rightNode) judgeIfZero = generateJudgeZero(rNode) requireNode1 = generateRequire() binaryNode1 = generateBinaryExp('/', lNode, rNode) tmpIdNode = TreeNode('Identifier') tmpIdNode.attributes = {'value': 'tmp'} binaryTotal1 = generateBinaryExp('==', binaryNode1, tmpIdNode) requireNode1.children.append(binaryTotal1) expNode1 = generateExpStatement() expNode1.children.append(requireNode1) judgeIfZero.children.append(expNode1) orgBlockNode.children.insert(idx + 1, tmpVarNode) orgBlockNode.children.insert(idx + 2, judgeIfZero) elif operator == '/=': pass
def generateExpStatement(): node = TreeNode('ExpressionStatement') node.beginPoint = -1 return node
def repair_second_type(ast, varDec): newvarNode = TreeNode('Identifier') newvarNode.attributes = {} newvarNode.attributes['value'] = varDec.children[0].attributes['name'] if (varDec.children[1].nodeType == 'BinaryOperation'): lnode = varDec.children[1].children[0] rnode = varDec.children[1].children[1] operator = varDec.children[1].attributes['operator'] if operator == '+': requireNode = generateRequire() binaryNode1 = generateBinaryExp('>=', newvarNode, lnode) binaryNode2 = generateBinaryExp('>=', newvarNode, rnode) binaryTotal = generateBinaryExp('&&', binaryNode1, binaryNode2) expStatementNode = generateExpStatement() requireNode.children.append(binaryTotal) expStatementNode.children.append(requireNode) orgBlockNode = varDec.father idx = orgBlockNode.children.index(varDec) orgBlockNode.children.insert(idx + 1, expStatementNode) elif operator == '-': requireNode = generateRequire() binaryTotal = generateBinaryExp('>=', lnode, rnode) expStatementNode = generateExpStatement() requireNode.children.append(binaryTotal) expStatementNode.children.append(requireNode) orgBlockNode = varDec.father idx = orgBlockNode.children.index(varDec) orgBlockNode.children.insert(idx, expStatementNode) elif operator == '*': judgeIfZero1 = generateJudgeZero(lnode) requireNode1 = generateRequire() binaryNode1 = generateBinaryExp('/', newvarNode, lnode) binaryTotal1 = generateBinaryExp('==', binaryNode1, rnode) requireNode1.children.append(binaryTotal1) expNode1 = generateExpStatement() expNode1.children.append(requireNode1) judgeIfZero1.children.append(expNode1) judgeIfZero2 = generateJudgeZero(rnode) requireNode2 = generateRequire() binaryNode2 = generateBinaryExp('/', newvarNode, rnode) binaryTotal2 = generateBinaryExp('==', binaryNode2, lnode) requireNode2.children.append(binaryTotal2) expNode2 = generateExpStatement() expNode2.children.append(requireNode2) judgeIfZero2.children.append(expNode2) orgBlockNode = varDec.father idx = orgBlockNode.children.index(varDec) orgBlockNode.children.insert(idx + 1, judgeIfZero1) orgBlockNode.children.insert(idx + 1, judgeIfZero2) elif operator == '/': pass else: pass
def repair_hard_encode(ast, charno): hard_encode_cnt = 0 for num in charno: try: defectNode = BFSGetNode(ast, num) # it is in a function if defectNode.father.father.nodeType == 'FunctionDefinition': literalNode = None nodeQ = Queue() nodeQ.put(defectNode) # root while (not nodeQ.empty()): tmpNode = nodeQ.get() if hasattr(tmpNode, 'attributes' ) and 'value' in tmpNode.attributes.keys(): if tmpNode.attributes[ 'value'] != None and tmpNode.attributes[ 'value'].startswith('0x'): literalNode = tmpNode for childNode in tmpNode.children: nodeQ.put(childNode) # if literalNode.father.nodeType == 'IndexAccess': # goalType = 'address' # currently this way # else: # goalType = defectNode.children[0].children[0].attributes['type'] goalType = 'address' #print(goalType) funcDefNode = defectNode.father.father typeNode = TreeNode('ElementaryTypeName') typeNode.attributes = {} typeNode.attributes['name'] = goalType typeNode.attributes['type'] = goalType varDecNode = TreeNode('VariableDeclaration') varDecNode.attributes = {} varDecNode.attributes['name'] = 'param' + str(hard_encode_cnt) varDecNode.children.append(typeNode) funcDefNode.children[0].children.append(varDecNode) idenNode = TreeNode('Identifier') idenNode.attributes = {} idenNode.attributes['value'] = 'param' + str(hard_encode_cnt) idx = literalNode.father.children.index(literalNode) literalNode.father.children[idx] = idenNode else: # print('cannot repair it') pass hard_encode_cnt += 1 except: print('failing to repair the hard encode defect in charnum:' + str(num)) continue
def generateThrowNode(): node = TreeNode('Throw') blockNode = TreeNode('Block') blockNode.children.append(node) return blockNode