def test_path_between_returns_True_only_if_there_exists_at_least_a_path_between_two_nodes_in_the_slice( self): my_slice = CFGSliceToSink(None, {1: [2, 3], 2: [4]}) self.assertTrue(my_slice.path_between(1, 2)) self.assertTrue(my_slice.path_between(1, 3)) self.assertTrue(my_slice.path_between(2, 4)) self.assertTrue(my_slice.path_between(1, 4)) self.assertFalse(my_slice.path_between(3, 4))
def test_add_transitions_updates_the_slice(self): my_slice = CFGSliceToSink(None, {1: [2, 3]}) transitions_to_add = {1: [4], 2: [4]} result = my_slice.add_transitions(transitions_to_add) expected_result = { 1: [2, 3, 4], 2: [4], } self.assertDictEqual(result, expected_result)
def test_transitions_as_tuples(self): my_slice = CFGSliceToSink(None, {1: [2, 3], 2: [3]}) expected_result = [(1, 2), (1, 3), (2, 3)] result = my_slice.transitions_as_tuples self.assertListEqual(result, expected_result)
def test_nodes(self): my_slice = CFGSliceToSink(None, { 1: [2, 3], 2: [3], }) expected_result = [1, 2, 3] result = my_slice.nodes self.assertListEqual(result, expected_result)
def test_slice_cfg_graph_mutates_the_original_graph(self): my_graph, nodes = _a_graph_and_its_nodes() transitions = {nodes[0].addr: [nodes[1].addr]} my_slice = CFGSliceToSink(None, transitions) sliced_graph = slice_cfg_graph(my_graph, my_slice) self.assertEqual(len(my_graph.nodes), 2) self.assertEqual(len(my_graph.edges), 1) self.assertEqual(my_graph, sliced_graph)
def test_init_the_call_stack_with_a_slice_as_subject_does_not_change_the_call_stack( self): binary_path = _binary_path('all') project = angr.Project(binary_path, load_options={'auto_load_libs': False}) initial_call_stack = [] reaching_definitions = project.analyses.ReachingDefinitions( subject=CFGSliceToSink(None, {}), call_stack=initial_call_stack) self.assertEqual(reaching_definitions._call_stack, initial_call_stack)
def test_slice_function_graph_mutates_the_original_function_graph(self): # Imagine a CFG being: 0 -> 0x42, 0x42 -> 1, 1 -> 2, 0 -> 3 # And the function graph: 0 -> 1, 1 -> 2, 0 -> 3 my_function_graph, nodes = _a_graph_and_its_nodes() transitions = {nodes[0].addr: [0x42], 0x42: [nodes[1].addr]} my_slice = CFGSliceToSink(None, transitions) sliced_function_graph = slice_function_graph(my_function_graph, my_slice) self.assertEqual(len(my_function_graph.nodes), 2) self.assertEqual(len(my_function_graph.edges), 1) self.assertEqual(my_function_graph, sliced_function_graph)
def test_slice_function_graph_remove_nodes_not_in_a_cfg_slice_to_sink( self): # Imagine a CFG being: 0 -> 0x42, 0x42 -> 1, 1 -> 2, 0 -> 3 # And the function graph: 0 -> 1, 1 -> 2, 0 -> 3 my_function_graph, nodes = _a_graph_and_its_nodes() transitions = {nodes[0].addr: [0x42], 0x42: [nodes[1].addr]} my_slice = CFGSliceToSink(None, transitions) sliced_function_graph = slice_function_graph(my_function_graph, my_slice) result_nodes = list(sliced_function_graph.nodes) result_edges = list(sliced_function_graph.edges) self.assertListEqual(result_nodes, [nodes[0], nodes[1]]) self.assertListEqual(result_edges, [(nodes[0], nodes[1])])
def test_slice_cfg_graph_remove_content_not_in_a_cfg_slice_to_sink(self): my_graph, nodes = _a_graph_and_its_nodes() transitions = { nodes[0].addr: [nodes[1].addr], nodes[1].addr: [nodes[2].addr] } my_slice = CFGSliceToSink(None, transitions) sliced_graph = slice_cfg_graph(my_graph, my_slice) result_nodes = list(sliced_graph.nodes) result_edges = list(sliced_graph.edges) self.assertListEqual(result_nodes, [nodes[0], nodes[1], nodes[2]]) self.assertListEqual(result_edges, [(nodes[0], nodes[1]), (nodes[1], nodes[2])])
def test_slice_callgraph_mutates_the_original_graph(self): my_callgraph, nodes = _a_graph_and_its_nodes() # Let's imagine a node (0x42), not a function entry point, not in my_callgraph, such as: # 1 -> 0x42, 0x42 -> 2 transitions = { nodes[0]: [nodes[1]], nodes[1]: [0x42], 0x42: [nodes[2]] } cfg_slice_to_sink = CFGSliceToSink(None, transitions) sliced_callgraph = slice_callgraph(my_callgraph, cfg_slice_to_sink) self.assertEqual(len(my_callgraph.nodes), 3) self.assertEqual(len(my_callgraph.edges), 2) self.assertEqual(my_callgraph, sliced_callgraph)
def test_slice_callgraph_remove_content_not_in_a_cfg_slice_to_sink(self): my_callgraph, nodes = _a_graph_and_its_nodes() # Let's imagine a node (0x42), not a function entry point, not in my_callgraph, such as: # 1 -> 0x42, 0x42 -> 2 transitions = { nodes[0]: [nodes[1]], nodes[1]: [0x42], 0x42: [nodes[2]] } cfg_slice_to_sink = CFGSliceToSink(None, transitions) sliced_callgraph = slice_callgraph(my_callgraph, cfg_slice_to_sink) result_nodes = list(sliced_callgraph.nodes) result_edges = list(sliced_callgraph.edges) self.assertListEqual(result_nodes, [nodes[0], nodes[1], nodes[2]]) self.assertListEqual(result_edges, [(nodes[0], nodes[1]), (nodes[1], nodes[2])])
def disable_emptyness(self): # disabled since binaries-private is not checked out for angr CI binaries_path = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'binaries-private', 'operation-mango') binary_path = os.path.join(binaries_path, 'air-live-bu-2015', 'cgi_test.cgi') project = Project(binary_path, auto_load_libs=False) cfg = project.analyses.CFGFast() printf = cfg.kb.functions.function(name='printf', plt=False) printf_node = cfg.model.get_all_nodes(printf.addr)[0] printf_predecessor = printf_node.predecessors[0] empty_slice = CFGSliceToSink(printf, {}) non_empty_slice = CFGSliceToSink( printf, {printf_predecessor.addr: [printf.addr]}) self.assertEqual(empty_slice.is_empty(), True) self.assertEqual(non_empty_slice.is_empty(), False)
def test_can_be_instantiated_with_a_slice(_): cfg_slice_to_sink = CFGSliceToSink(None, {}) subject = Subject(cfg_slice_to_sink, None) nose.tools.assert_equals(subject.content, cfg_slice_to_sink) nose.tools.assert_equals(subject.type, SubjectType.CFGSliceToSink)
def test_path_between_deals_with_loops(self): my_slice = CFGSliceToSink(None, {1: [2, 3], 2: [1]}) self.assertFalse(my_slice.path_between(1, 4))
def test_get_transitions_from_slice(self): transitions = {1: [2, 3]} my_slice = CFGSliceToSink(None, transitions) self.assertDictEqual(my_slice.transitions, transitions)
def test_get_entrypoints_from_slice(self): transitions = {0: [2], 1: [2, 3], 2: [4, 5]} my_slice = CFGSliceToSink(None, transitions) self.assertListEqual(my_slice.entrypoints, [0, 1])