Exemple #1
0
    def test_assign_weights_wo_defaults(self):
        # Arrange
        target = CallGraph(
            source='/tmp',
            graph=self._build_graph(),
            load_errors=list(),
        )
        weights = {
            "base": {
                "call": 125,
                "return": 75
            },
            "dangerous": 35,
            "defense": -30,
            "tested": -25,
            "vulnerable": 35
        }
        expected = {
            ('main', 'read'): 100,
            ('read', 'main'): 50,
            ('main', 'write'): 135,
            ('write', 'main'): 50,
            ('main', 'parse'): 125,
            ('parse', 'main'): 50,
            ('main', 'analyze'): 135,
            ('analyze', 'main'): 50,
            ('main', 'memalloc'): 140,
            ('memalloc', 'main'): 50,
            ('read', 'readfile'): 100,
            ('readfile', 'read'): 50,
            ('read', 'validate'): 70,
            ('validate', 'read'): 50,
            ('write', 'writefile'): 100,
            ('writefile', 'write'): 85,
            ('parse', 'parsefile'): 160,
            ('parsefile', 'parse'): 75,
            ('analyze', 'analyzefile'): 125,
            ('analyzefile', 'analyze'): 85
        }

        # Act
        target.assign_weights(weights)
        actual = nx.get_edge_attributes(target.call_graph, 'weight')

        # Assert
        self.assertCountEqual(expected, actual)
        for i in expected:
            self.assertEqual(expected[i], actual[i], msg=i)
Exemple #2
0
    def test_call_graph_w_fragmentize(self):
        # Arrange

        #   a -- b   e -- f -- g
        #   |    |
        #   |    |
        #   d -- c   h -- i  j
        graph = nx.DiGraph()
        graph.add_nodes_from(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'])
        graph.add_edges_from([('a', 'b'), ('b', 'a'), ('b', 'c'), ('c', 'b'),
                              ('c', 'd'), ('d', 'c'), ('d', 'a'), ('a', 'd'),
                              ('e', 'f'), ('f', 'e'), ('f', 'g'), ('g', 'f'),
                              ('h', 'i'), ('i', 'h')])
        expected = nx.DiGraph()
        expected.add_nodes_from(['a', 'b', 'c', 'd'])
        expected.add_edges_from([('a', 'b'), ('b', 'a'), ('b', 'c'),
                                 ('c', 'b'), ('c', 'd'), ('d', 'c'),
                                 ('d', 'a'), ('a', 'd')])

        # Act
        actual = CallGraph(source='/tmp',
                           graph=graph,
                           load_errors=list(),
                           fragmentize=True)

        # Assert
        self.assertEqual(4, actual.num_fragments)
        self.assertEqual(0.4, actual.monolithicity)
        self.assertCountEqual(expected.nodes(), [i for (i, _) in actual.nodes])
        self.assertCountEqual(expected.edges(),
                              [(i, j) for (i, j, _) in actual.edges])
 def setUp(self):
     self.target = CallGraph.from_loader(
         CflowLoader(
             os.path.join(
                 os.path.dirname(os.path.realpath(__file__)),
                 'helloworld/cflow.callgraph.r.txt'
             ),
             True
         )
     )
 def setUp(self):
     self.target = CallGraph.from_loader(
         CflowLoader(
             os.path.join(
                 os.path.dirname(os.path.realpath(__file__)),
                 'helloworld'
             ),
             False
         )
     )
 def setUp(self):
     self.target = CallGraph.from_loader(
         CflowLoader(
             os.path.join(
                 os.path.dirname(os.path.realpath(__file__)),
                 'helloworld/cflow.callgraph.txt'
             ),
             False
         ),
         granularity=Granularity.FILE
     )
 def setUp(self):
     self.target = CallGraph.from_merge(
         CallGraph.from_loader(
             CflowLoader(
                 os.path.join(
                     os.path.dirname(os.path.realpath(__file__)),
                     'helloworld/cflow.callgraph.r.txt'
                 ),
                 True
             ),
             granularity=Granularity.FILE
         ),
         CallGraph.from_loader(
             GprofLoader(
                 os.path.join(
                     os.path.dirname(os.path.realpath(__file__)),
                     'helloworld/gprof.callgraph.txt'
                 )
             ),
             granularity=Granularity.FILE
         )
     )
Exemple #7
0
    def test_assign_weights_w_defaults(self):
        # Arrange
        target = CallGraph(
            source='/tmp',
            graph=self._build_graph(),
            load_errors=list(),
        )
        expected = {
            ('main', 'read'): 75,
            ('read', 'main'): 25,
            ('main', 'write'): 100,
            ('write', 'main'): 25,
            ('main', 'parse'): 100,
            ('parse', 'main'): 25,
            ('main', 'analyze'): 100,
            ('analyze', 'main'): 25,
            ('main', 'memalloc'): 100,
            ('memalloc', 'main'): 25,
            ('read', 'readfile'): 75,
            ('readfile', 'read'): 25,
            ('read', 'validate'): 50,
            ('validate', 'read'): 25,
            ('write', 'writefile'): 75,
            ('writefile', 'write'): 50,
            ('parse', 'parsefile'): 125,
            ('parsefile', 'parse'): 50,
            ('analyze', 'analyzefile'): 100,
            ('analyzefile', 'analyze'): 50
        }

        # Act
        target.assign_weights()
        actual = nx.get_edge_attributes(target.call_graph, 'weight')

        # Assert
        self.assertCountEqual(expected, actual)
        for i in expected:
            self.assertEqual(expected[i], actual[i], msg=i)
Exemple #8
0
    def setUp(self):
        call_graph = CallGraph.from_loader(
            CflowLoader(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'helloworld')))

        self.formatter = HtmlFormatter(call_graph)

        self.formatter_output_file = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'helloworld/formatter.output.html')

        self.formatter_summary_file = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'helloworld/formatter.summary.html')
    def setUp(self):
        call_graph = CallGraph.from_loader(
            CflowLoader(
                os.path.join(
                    os.path.dirname(os.path.realpath(__file__)),
                    'helloworld'
                )
            )
        )

        self.formatter = HtmlFormatter(call_graph)

        self.formatter_output_file = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'helloworld/formatter.output.html'
        )

        self.formatter_summary_file = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'helloworld/formatter.summary.html'
        )
Exemple #10
0
    def test_sanitize(self):
        # Arrange
        expected_nodes = [
            Call('', './src/helloworld.c', Env.C, Gran.FILE),
            Call('', './src/greetings.c', Env.C, Gran.FILE),
        ]
        expected_edges = [
            (Call('', './src/helloworld.c', Env.C,
                  Gran.FILE), Call('', './src/helloworld.c', Env.C,
                                   Gran.FILE)),
            (Call('', './src/greetings.c', Env.C,
                  Gran.FILE), Call('', './src/helloworld.c', Env.C,
                                   Gran.FILE)),
            (Call('', './src/helloworld.c', Env.C,
                  Gran.FILE), Call('', './src/greetings.c', Env.C, Gran.FILE)),
            (Call('', './src/greetings.c', Env.C,
                  Gran.FILE), Call('', './src/greetings.c', Env.C, Gran.FILE))
        ]

        # Act
        graph = CallGraph.from_loader(CflowLoader(
            os.path.join(os.path.dirname(os.path.realpath(__file__)),
                         'helloworld/cflow.callgraph.r.mod.txt'), True),
                                      granularity=Gran.FILE)
        edges = [(caller, callee) for (caller, callee, _) in graph.edges]
        all_edges_found = all([c in edges for c in expected_edges])

        nodes = [n for (n, _) in graph.nodes]
        all_nodes_found = (all([n in nodes for n in expected_nodes])
                           and all([n in expected_nodes for n in nodes]))

        # Assert
        self.assertEqual(len(expected_nodes), len(nodes))
        self.assertTrue(all_nodes_found)

        self.assertEqual(len(expected_edges), len(edges))
        self.assertTrue(all_edges_found)
    def test_fix(self):
        # Arrange
        target = CallGraph.from_loader(
            CflowLoader(
                os.path.join(
                    os.path.dirname(os.path.realpath(__file__)),
                    'helloworld/cflow.callgraph.r.mod.txt'
                ),
                True
            )
        )
        _target = copy.deepcopy(target)
        reference = CallGraph.from_loader(
            GprofLoader(
                os.path.join(
                    os.path.dirname(os.path.realpath(__file__)),
                    'helloworld/gprof.callgraph.txt'
                )
            )
        )
        expected = {
            'before': Call('GreeterSayHi', '', Environments.C),
            'after': Call('GreeterSayHi', './src/helloworld.c', Environments.C)
        }

        # Act
        utilities.fix(target, using=reference)
        actual = {
            'before':  next(
                i
                for (i, _) in _target.nodes
                if i.function_name == 'GreeterSayHi'
            ),
            'after':  next(
                i
                for (i, _) in target.nodes
                if i.function_name == 'GreeterSayHi'
            )
        }

        # Assert
        self.assertEqual(expected['before'], actual['before'])
        self.assertEqual(expected['after'], actual['after'])
        # Asserting if node attributes got carried over
        self.assertCountEqual(
            [
                attrs
                for (i, attrs) in _target.nodes
                if i == expected['before']
            ],
            [
                attrs
                for (i, attrs) in target.nodes
                if i == expected['after']
            ]
        )
        # Asserting if edge attributes got carried over
        self.assertCountEqual(
            [
                attrs
                for (i, j, attrs) in _target.edges
                if i == expected['before'] or j == expected['before']
            ],
            [
                attrs
                for (i, j, attrs) in target.edges
                if i == expected['after'] or j == expected['after']
            ],
        )
        # Asserting if OTHER nodes and their attributes got carried over
        self.assertCountEqual(
            [
                (i, attrs)
                for (i, attrs) in _target.nodes
                if i != expected['before']
            ],
            [
                (i, attrs)
                for (i, attrs) in target.nodes
                if i != expected['after']
            ]
        )
        # Asserting if OTHER edges and their attributes got carried over
        self.assertCountEqual(
            [
                (i, j, attrs)
                for (i, j, attrs) in _target.edges
                if i != expected['before'] and j != expected['before']
            ],
            [
                (i, j, attrs)
                for (i, j, attrs) in target.edges
                if i != expected['after'] and j != expected['after']
            ],
        )
Exemple #12
0
def main():
    args = parse_args()

    call_graph = None
    if args.javacg:
        loader = JavaCGLoader(args.javacg, args.apppackages)
        call_graph = CallGraph.from_loader(loader)
    else:
        cflow_loader = None
        gprof_loader = None
        if args.cflow:
            if not os.path.exists(args.cflow):
                raise Exception('{} not found.'.format(args.cflow))
            else:
                cflow_loader = CflowLoader(args.cflow, reverse=args.reverse)

        if args.gprof:
            if not os.path.exists(args.gprof):
                raise Exception('{} not found.'.format(args.gprof))
            else:
                if os.path.isdir(args.gprof):
                    sources = [
                        os.path.join(args.gprof, filename)
                        for filename in os.listdir(args.gprof)
                        if os.path.isfile(os.path.join(args.gprof, filename))
                    ]
                    gprof_loader = MultigprofLoader(sources,
                                                    processes=args.processes)
                else:
                    gprof_loader = GprofLoader(args.gprof)

        if cflow_loader and gprof_loader:
            call_graph = CallGraph.from_merge(
                CallGraph.from_loader(cflow_loader,
                                      granularity=args.granularity),
                CallGraph.from_loader(gprof_loader,
                                      granularity=args.granularity))
        elif cflow_loader:
            call_graph = CallGraph.from_loader(cflow_loader,
                                               granularity=args.granularity)
        elif gprof_loader:
            call_graph = CallGraph.from_loader(gprof_loader,
                                               granularity=args.granularity)

    if args.output:
        (name, extension) = os.path.splitext(args.output)
        output_format = extension.replace('.', '')
        if output_format not in FORMATTERS:
            output_format = 'txt'
        formatter = FORMATTERS[output_format](call_graph)
        with open(args.output, 'w') as file_:
            if args.verbose:
                file_.write(formatter.write_output())
            else:
                file_.write(formatter.write_summary())
    else:
        formatter = FORMATTERS['txt'](call_graph)
        if args.verbose:
            sys.stdout.write(formatter.write_output())
        else:
            sys.stdout.write(formatter.write_summary())

    if args.showerrors and call_graph.load_errors:
        sys.stdout.write('Parse Errors\n')
        sys.stdout.write('============\n')
        for error in call_graph.load_errors:
            sys.stdout.write(error)
def stat(**options):
    cflow_path = options.get('cflow_path', None)
    gprof_path = options.get('gprof_path', None)
    num_processes = options.get('num_processes')
    output = options.get('output', False)
    threshold = options.get('threshold', None)
    subject = options.get('subject', None)
    revision = options.get('revision', None)

    if subject not in settings.ENABLED_SUBJECTS:
        raise CommandError('Subject {0} is not enabled'.format(subject))

    cflow_loader = None
    gprof_loader = None

    cflow_call_graph = None
    gprof_call_graph = None

    begin = datetime.datetime.now()
    if cflow_path:
        fragmentize = False
        if not gprof_path:
            fragmentize = True

        print('Loading cflow call graph')
        cflow_loader = CflowLoader(cflow_path, reverse=True)
        cflow_call_graph = CallGraph.from_loader(cflow_loader, fragmentize)

    if gprof_path:
        fragmentize = False
        if not cflow_path:
            fragmentize = True

        print('Loading gprof call graph')
        if os.path.isdir(gprof_path):
            sources = [
                os.path.join(gprof_path, file_name)
                for file_name in os.listdir(gprof_path) if 'txt' in file_name
            ]
            os.environ['DEBUG'] = '1'
            gprof_loader = MultigprofLoader(sources, processes=num_processes)
            gprof_call_graph = CallGraph.from_loader(gprof_loader, fragmentize)
        else:
            gprof_loader = GprofLoader(gprof_path, reverse=False)
            gprof_call_graph = CallGraph.from_loader(gprof_loader, fragmentize)
    end = datetime.datetime.now()

    call_graph = None
    if cflow_call_graph and gprof_call_graph:
        if 'DEBUG' in os.environ:
            print()

        print('Merging cflow and gprof call graphs')
        call_graph = CallGraph.from_merge(cflow_call_graph,
                                          gprof_call_graph,
                                          fragmentize=True)
    elif cflow_call_graph:
        call_graph = cflow_call_graph
    elif gprof_call_graph:
        call_graph = gprof_call_graph

    if not call_graph:
        print('Nothing to stat. Exiting.')
        sys.exit(0)

    print('Load completed in {0:.2f} seconds'.format(
        (end - begin).total_seconds()))

    print('#' * 50)
    print('              Call Graph Statistics')
    print('#' * 50)
    print('    Nodes               {0}'.format(len(call_graph.nodes)))
    print('    Edges               {0}'.format(len(call_graph.edges)))
    print('    Entry Points        {0}'.format(len(call_graph.entry_points)))
    print('    Exit Points         {0}'.format(len(call_graph.exit_points)))
    print('    Dangerous           {0}'.format(
        len(nx.get_node_attributes(call_graph.call_graph, 'dangerous'))))
    print('    Monolithicity       {0:4f}'.format(call_graph.monolithicity))
    print('    Fragments           {0}'.format(call_graph.num_fragments))
    print('#' * 50)

    if output:
        generate(subject, revision, call_graph, threshold, num_processes)
 def setUp(self):
     self.target = CallGraph.from_loader(
         CflowLoader(
             os.path.join(os.path.dirname(os.path.realpath(__file__)),
                          'helloworld'), False))