def get_sink_args(cfg_node): if isinstance(cfg_node.ast_node, ast.Call): rhs_visitor = RHSVisitor() rhs_visitor.visit(cfg_node.ast_node) return rhs_visitor.result elif isinstance(cfg_node.ast_node, ast.Assign): return cfg_node.right_hand_side_variables elif isinstance(cfg_node, BBorBInode): return cfg_node.args else: vv = VarsVisitor() vv.visit(cfg_node.ast_node) return vv.result
def add_blackbox_or_builtin_call(self, node, blackbox): # noqa: C901 """Processes a blackbox or builtin function when it is called. Nothing gets assigned to ret_func_foo in the builtin/blackbox case. Increments self.function_call_index each time it is called, we can refer to it as N in the comments. Create e.g. ~call_1 = ret_func_foo RestoreNode. Create e.g. temp_N_def_arg1 = call_arg1_label_visitor.result for each argument. Visit the arguments if they're calls. (save_def_args_in_temp) I do not think I care about this one actually -- Create e.g. def_arg1 = temp_N_def_arg1 for each argument. (create_local_scope_from_def_args) Add RestoreNode to the end of the Nodes. Args: node(ast.Call) : The node that calls the definition. blackbox(bool): Whether or not it is a builtin or blackbox call. Returns: call_node(BBorBInode): The call node. """ self.function_call_index += 1 saved_function_call_index = self.function_call_index self.undecided = False call_label_visitor = LabelVisitor() call_label_visitor.visit(node) call_function_label = call_label_visitor.result[ : call_label_visitor.result.find("(") ] # Check if function call matches a blackbox/built-in alias and if so, resolve it # This resolves aliases like "from os import system as mysys" as: mysys -> os.system local_definitions = self.module_definitions_stack[-1] call_function_label = fully_qualify_alias_labels( call_function_label, local_definitions.import_alias_mapping ) # Create e.g. ~call_1 = ret_func_foo LHS = CALL_IDENTIFIER + "call_" + str(saved_function_call_index) RHS = "ret_" + call_function_label + "(" call_node = BBorBInode( label="", left_hand_side=LHS, ast_node=node, right_hand_side_variables=[], line_number=node.lineno, path=self.filenames[-1], func_name=call_function_label, ) visual_args = list() rhs_vars = list() last_return_value_of_nested_call = None for arg_node in itertools.chain(node.args, node.keywords): arg = arg_node.value if isinstance(arg_node, ast.keyword) else arg_node if isinstance(arg, ast.Call): return_value_of_nested_call = self.visit(arg) if last_return_value_of_nested_call: # connect inner to other_inner in e.g. # `scrypt.outer(scrypt.inner(image_name), scrypt.other_inner(image_name))` # I should probably loop to the inner most call of other_inner here. try: last_return_value_of_nested_call.connect( return_value_of_nested_call.first_node ) except AttributeError: last_return_value_of_nested_call.connect( return_value_of_nested_call ) else: # I should only set this once per loop, inner in e.g. # `scrypt.outer(scrypt.inner(image_name), scrypt.other_inner(image_name))` # (inner_most_call is used when predecessor is a ControlFlowNode in connect_control_flow_node) call_node.inner_most_call = return_value_of_nested_call last_return_value_of_nested_call = return_value_of_nested_call if isinstance(arg_node, ast.keyword) and arg_node.arg is not None: visual_args.append( arg_node.arg + "=" + return_value_of_nested_call.left_hand_side ) else: if hasattr(return_value_of_nested_call, "left_hand_side"): visual_args.append(return_value_of_nested_call.left_hand_side) if hasattr(return_value_of_nested_call, "left_hand_side"): rhs_vars.append(return_value_of_nested_call.left_hand_side) else: label = LabelVisitor() label.visit(arg_node) visual_args.append(label.result) vv = VarsVisitor() vv.visit(arg_node) rhs_vars.extend(vv.result) if last_return_value_of_nested_call: # connect other_inner to outer in e.g. # `scrypt.outer(scrypt.inner(image_name), scrypt.other_inner(image_name))` last_return_value_of_nested_call.connect(call_node) call_names = list(get_call_names(node.func)) if len(call_names) > 1: # taint is a RHS variable (self) of taint.lower() rhs_vars.append(call_names[0]) if len(visual_args) > 0: for arg in visual_args: RHS = RHS + arg + ", " # Replace the last ", " with a ) RHS = RHS[: len(RHS) - 2] + ")" else: RHS = RHS + ")" call_node.label = LHS + " = " + RHS call_node.right_hand_side_variables = rhs_vars # Used in get_sink_args rhs_visitor = RHSVisitor() rhs_visitor.visit(node) call_node.args = rhs_visitor.result if blackbox: self.blackbox_assignments.add(call_node) self.connect_if_allowed(self.nodes[-1], call_node) self.nodes.append(call_node) return call_node