Source code for badsnakes.libs.reporter

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
:Purpose:   This module provides the *terminal-based* reporting
            functionality for the project. File-based reporting is
            handled by the :mod:`badsnakes.libs.logger` module.

            There is a specific reporting class, based on the analysis
            provided:

                - :class:`ReporterModule`
                - :class:`ReporterPickle`
                - :class:`ReporterWheel`

            All of these classes inherit their base functionality from
            the private :class:`_ReporterBase` class.

:Platform:  Linux/Windows | Python 3.10+
:Developer: J Berendt
:Email:     development@s3dev.uk

:Comments:  This module's implementation is very simple in that it only
            iterates a module's node classes and calls the ``.report()``
            method on each container, which provides the *formatting*
            for each message. The formatting is *not* controlled by this
            module.

            For example:

                - :meth:`badsnakes.libs.containers.Assign.report`
                - :meth:`badsnakes.libs.containers.Attribute.report`
                - :meth:`badsnakes.libs.containers.Call.report`
                - etc.

"""

# Enable type hinting
from __future__ import annotations


[docs] class _ReporterBase: """Currently not implemented."""
[docs] class ReporterModule(_ReporterBase): """Iterate all modules and report the findings for each node type. Args: modules (list[module.Module] | tuple[module.Module]): A list (or tuple) of :class:`badsnakes.libs.module.Module` objects containing the findings to be reported. """ def __init__(self, modules: list[module.Module] | tuple[module.Module]): # noqa # pylint: disable=undefined-variable """Base reporter initialiser class.""" self._mods = modules if isinstance(modules, (list, tuple)) else [modules] self._m = None # Module currently being reported.
[docs] def report(self): """Primary reporting callable. This method iterates the modules provided on instantiation of the :class:`ReporterModule` class, and reports the node-class-specific findings for each. """ for m in self._mods: self._m = m self._display_title() self._report_suspect() self._report_dangerous() self._report_classification()
[docs] def report_classification_only(self): """Reporting callable for displaying the *classification only*. This method iterates the modules provided on instantiation of the :class:`ReporterModule` class, and reports each module's classification. """ for m in self._mods: self._m = m self._report_classification_only()
[docs] def _display_title(self): """Display a formatted version of the current module's name.""" title = f' Module: {self._m.name_and_parent} ' sep = '-' * len(title) print('', sep, title, sep, sep='\n')
[docs] def _report_classification(self): """Report the current module's overall classification.""" print('\nModule classification:', self._m.classification.name)
[docs] def _report_classification_only(self): """Report the current module's overall classification. This method differs from the :meth:`_report_classification` in that this method also displays the module name, as the :meth:`report_classification_only` method does not print the module name in a title banner. """ print(f'Module: {self._m.name_and_parent}, Classification: {self._m.classification.name}')
[docs] def _report_dangerous(self): """For each node class, report the *dangerous* findings.""" for nc in self._m.nodeclasses: for i in nc.analyser.dangerous: i.report() for i in nc.analyser.dangerous_longstring: i.report_longstring()
[docs] def _report_suspect(self): """For each node class, report the *suspect* findings.""" for nc in self._m.nodeclasses: for i in nc.analyser.suspect: i.report() for i in nc.analyser.suspect_longstring: i.report_longstring()
[docs] class ReporterPickle(_ReporterBase): """Report findings for a given pickle file. Raises: NotImplementedError: Currently not implemented. Available for future development. """ def __init__(self): """Pickle analysis reporter class initialiser.""" raise NotImplementedError('Pickle analysis is not implemented (yet).')
[docs] class ReporterWheel(_ReporterBase): """Report findings for all plaintext files in a given wheel. Raises: NotImplementedError: Currently not implemented. Available for future development. """ def __init__(self): """Wheel analysis reporter class initialiser.""" raise NotImplementedError('Wheel analysis is not implemented (yet).')