Fuzz Introspector core modules

Core modules in the Fuzz Introspector package

fuzz_introspector.analysis

Performs analysis on the profiles output from fuzz introspector LLVM pass

class fuzz_introspector.analysis.AnalysisInterface

Bases: ABC

abstract analysis_func(table_of_contents: HtmlTableOfContents, tables: List[str], proj_profile: MergedProjectProfile, profiles: List[FuzzerProfile], basefolder: str, coverage_url: str, conclusions: List[HTMLConclusion]) str

Entrypoint for analysis instance. This function can have side effects on many of the arguments passed to it.

Parameters:
  • table_of_contents (html_helpers.HtmlTableOfContents) – table of content list for adding sections to HTML report.

  • tables (List[str]) – list of table ids to be styled in the report.

  • proj_profile (project_profile.MergedProjectProfile) – project profile involved in the analysis.

  • profiles (List[fuzzer_profile.FuzzerProfile]) – all fuzzer profiles involved in the current analysis.

  • basefolder (str) – Basefolder of the files as placed on the file system.

  • coverage_url (str) – Base coverage URL.

  • conclusions (List[html_helpers.HTMLConclusion]) – List of high level conclusions to be shown in the final report. Append to this list any conclusions that should be shown at the top of the report page.

Return type:

str

Returns:

A string that corresponds to HTML that can be embedded in the html report.

abstract get_json_string_result()

Return json_string_result

abstract classmethod get_name()

Return name of analysis

abstract set_json_string_result(string)

Return json_string_result

class fuzz_introspector.analysis.IntrospectionProject(language, target_folder, coverage_url)

Bases: object

Wrapper class for managing Fuzz Introspector analysis.

The most important two elments of this class are proj_profile which is type project_profile.MergedProjectProfile and profiles which is a list of fuzzer_profile.FuzzerProfile and references the individual fuzzers of the given module. All analysis is done basically by way of these two elements.

fuzz_introspector.analysis.get_hit_count_color(hit_count: int) str

Map hitcount to color of target

fuzz_introspector.analysis.get_node_coverage_hitcount(demangled_name: str, callstack: Dict[int, str], node: CalltreeCallsite, profile: FuzzerProfile, is_first: bool) int

Extracts the runtime coverage hitcount of a node in the calltree

Gets the coverage callsite link of a given node.

fuzz_introspector.analysis.get_url_to_cov_report(profile, node, target_coverage_url)

Get URL to coverage report for the node.

fuzz_introspector.analysis.instantiate_analysis_interface(cls: Type[AnalysisInterface])

Wrapper function to satisfy Mypy semantics

fuzz_introspector.analysis.update_branch_complexities(all_functions: Dict[str, FunctionProfile], coverage: CoverageProfile) None

Traverse every branch profile and update the side complexities based on reached funcs complexity.

fuzz_introspector.cfg_load

Module for loading CFG files

class fuzz_introspector.cfg_load.CalltreeCallsite(dst_function_name: str, dst_function_source_file: str, depth: int, src_linenumber: int, parent_calltree_callsite: Optional[CalltreeCallsite])

Bases: object

Represents a single node in the calltree

fuzz_introspector.cfg_load.data_file_read_calltree(filename: str) Optional[CalltreeCallsite]

Extracts the calltree of a fuzzer from a .data file. This is for C/C++ files

Returns a CalltreeCallsite that is the root of the tree read.

fuzz_introspector.cfg_load.extract_all_callsites_recursive(calltree: CalltreeCallsite, callsite_nodes: List[CalltreeCallsite]) None

Given a node, will assemble all callsites in the children. Recursive function.

fuzz_introspector.commands

High-level routines and CLI entrypoints

fuzz_introspector.constants

fuzz_introspector.code_coverage

Module for handling code coverage reports

class fuzz_introspector.code_coverage.CoverageProfile

Bases: object

Stores and handles a runtime coverage data.

Variables:
  • covmap (Dict[str, List[Tuple[int, int]]]) –

    Dictionary of string to list of tuples of ints. The tuples correspond to line number and hitcount. The string can have multiple meanings depending on the language being handled. For C/C++ it corresponds to functions, and for Python it correspond to source code files.

    If the key is file paths then set_type returns “file”.

  • file_map (Dict[str, List[Tuple[int, int]]]) – Dictionary holding mappings between source code files and line numbers and hitcounts.

  • branch_cov_map (Dict[str, Tuple[int, int]]) – Dictionary to collect the branch coverage info in the form of current_func:line_number as the key and list of hitcounts as value.

get_hit_details(funcname: str) List[Tuple[int, int]]

Returns details of code coverage for a given function.

This should only be used for coverage profiles that are non-file type.

Parameters:

funcname (str) – Function name to lookup.

Return type:

List[Tuple[int, int]]

Returns:

List of pairs where the first element is the source code linenumber and the second element is the amount of times that line was covered.

get_hit_summary(funcname: str) Tuple[Optional[int], Optional[int]]

Returns the hit summary of a give function.

This should only be used for coverage profiles that are non-file type.

Parameters:

funcname (str) – Function name to lookup.

Return type:

List[Tuple[Optional[int], Optional[int]]]

Returns:

List of pairs where the first element is the total amount of lines in a function and second element is the amount of lines in the function that are hit.

is_file_lineno_hit(target_file: str, lineno: int, resolve_name: bool = False) bool

Checks if a given linenumber in a file is hit.

Parameters:
  • target_file (str) – file to inspect

  • lineno (int) – line number in the file

  • resolve_name (bool) – whether to normalise name. This is only used for Python code coverage where the filename being tracked is extracted from a pyinstaller executable.

Return type:

bool

Returns:

True if lineno is covered in the given soruce file. False otherwise.

is_func_hit(funcname: str) bool

Returs whether a function is hit

is_func_lineno_hit(func_name: str, lineno: int) bool

Checks if a given line number in a function is hit.

fuzz_introspector.code_coverage.extract_hitcount(input: str) int

Extract the count from coverage format hitcount: 4.68k or 5.2M. The caller has to check for error returns before using the value.

fuzz_introspector.code_coverage.load_jvm_coverage(target_dir: str, target_name: Optional[str] = None) CoverageProfile

Find and load jacoco.xml, a jvm xml coverage report file

The xml file is generated from Jacoco plugin. The specific dtd of the xml can be found in the following link: - https://www.jacoco.org/jacoco/trunk/coverage/report.dtd

Return a CoverageProfile

fuzz_introspector.code_coverage.load_llvm_coverage(target_dir: str, target_name: Optional[str] = None) CoverageProfile

Scans a directory to read one or more coverage reports, and returns a CoverageProfile

Parses output from “llvm-cov show”, e.g.

llvm-cov show -instr-profile=$profdata_file -object=$target -line-coverage-gt=0 $shared_libraries $LLVM_COV_COMMON_ARGS > ${FUZZER_STATS_DIR}/$target.covreport

This is used to parse C/C++ coverage.

The function supports loading multiple and individual coverage reports. This is needed because finding coverage on a per-fuzzer basis requires correlating binary files to a specific introspection profile from compile time. However, files could be moved around, renamed, and so on.

As such, this function accepts an arugment “target_name” which is used to target specific coverage profiles. However, if no coverage profile matches that given name then the function will find all coverage reports it can and use all of them.

fuzz_introspector.code_coverage.load_python_json_coverage(json_file: str, strip_pyinstaller_prefix: bool = True)

Loads a python json coverage file.

The specific json file that is handled by the coverage output from: - https://coverage.readthedocs.io/en/latest/cmd.html#json-reporting-coverage-json

Return a CoverageProfile

fuzz_introspector.data_loader

Reads the data output from the fuzz introspector LLVM plugin.

fuzz_introspector.data_loader.load_all_profiles(target_folder: str, language: str, parallelise: bool = True) List[FuzzerProfile]

Loads all profiles in target_folder in a multi-threaded manner

fuzz_introspector.data_loader.read_fuzzer_data_file_to_profile(cfg_file: str, language: str) Optional[FuzzerProfile]

For a given .data file (CFG) read the corresponding .yaml file This is a bit odd way of doing it and should probably be improved.

fuzz_introspector.data_loader.try_load_input_bugs() List[Bug]

Loads input bugs as list. Returns empty list if none

fuzz_introspector.exceptions

Exceptions used throughout the package.

exception fuzz_introspector.exceptions.AnalysisError

Bases: FuzzIntrospectorError

Error for analysis logic

exception fuzz_introspector.exceptions.CalltreeError

Bases: FuzzIntrospectorError

Error for when dealing with calltrees

exception fuzz_introspector.exceptions.DataLoaderError

Bases: FuzzIntrospectorError

Error for handling data loader issues

exception fuzz_introspector.exceptions.FuzzIntrospectorError

Bases: Exception

Base error

fuzz_introspector.html_helpers

Module for creating HTML reports

class fuzz_introspector.html_helpers.HTMLConclusion(severity, title, description)

Bases: object

Represents high-level conclusions in HTML report

Variables:
  • severity (int) – Importance of conclusion. 100 max, 0 lowest.

  • title (str) – One line description of conclusion.

  • description (str) – Extended description.

class fuzz_introspector.html_helpers.HTML_HEADING(value)

Bases: Enum

An enumeration.

class fuzz_introspector.html_helpers.HTML_TOC_ENTRY(entry_title: str, href_link: str, heading_type: HTML_HEADING)

Bases: object

Entry in the table of contents

class fuzz_introspector.html_helpers.HtmlTableOfContents

Bases: object

Helper class for representing a table of content

fuzz_introspector.html_helpers.create_collapsible_element(non_collapsed: str, collapsed: str, collapsible_id: str) str

Creates a string followed by a <div> that is collapsible. We use this for displaying items in tables where the full substance of the item is too large to display by default for all items, but we still want the user to be able to see the full substance of the item on demand.

fuzz_introspector.html_helpers.create_conclusions_box(conclusions: List[HTMLConclusion]) str

Creates a <div> with all conclusions displayed. Conclusions of highest severity are placed lowest (positive conclusiosn at top, negative at bottom).

fuzz_introspector.html_helpers.create_horisontal_calltree_image(image_name: str, profile: FuzzerProfile, dump_files: bool) List[str]

Creates a horisontal image of the calltree. The height is fixed and each element on the x-axis shows a node in the calltree in the form of a rectangle. The rectangle is red if not visited and green if visited.

fuzz_introspector.html_helpers.create_percentage_graph(title: str, numerator: int, denominator: int) str

Creates a percentage tag within a <div> tag. This is used to show “how much X is of Y” for a {numerator, denominator} pair.

fuzz_introspector.html_helpers.get_simple_box(title: str, value: str) str

Wraps a title and value in a simle HTML div box, where the box has some simple borders.

fuzz_introspector.html_helpers.prettify_html(html_doc: str) str

Prettify a HTML document.

fuzz_introspector.html_report

Module for creating HTML reports

fuzz_introspector.html_report.create_all_function_table(tables: List[str], proj_profile: MergedProjectProfile, coverage_url: str, basefolder: str, table_id: Optional[str] = None) Tuple[str, List[Dict[str, Any]], List[Dict[str, Any]]]

Table for all functions in the project. Contains many details about each function

Create an array of table ids wrapped in a <script> tag, and close <body> and <html> tags.

fuzz_introspector.html_report.create_html_report(introspection_proj: IntrospectionProject, analyses_to_run, output_json, report_name, dump_files) None

Logs a complete report. This is the current main place for looking at data produced by fuzz introspector. This method will return a dict contains analyser name to instance mapping that requires separate json report generation to avoid reruning those analysing process.

fuzz_introspector.html_report.create_overview_table(tables: List[str], profiles: List[FuzzerProfile]) str

Table with an overview of all the fuzzers

fuzz_introspector.html_report.create_section_all_functions(table_of_contents, tables, proj_profile, coverage_url, basefolder)

Table with details about all functions in the target project.

fuzz_introspector.html_report.create_section_fuzzer_detailed_section(table_of_contents, profiles, proj_profile, tables, conclusions, fuzzer_table_data, dump_files)

Section with details about each fuzzer, including calltree.

fuzz_introspector.html_report.create_section_fuzzers_overview(table_of_contents, tables, profiles) str

Section with table with overview of all fuzzers.

fuzz_introspector.html_report.create_section_optional_analyses(table_of_contents, analyses_to_run, output_json, tables, proj_profile, profiles, basefolder, coverage_url, conclusions, dump_files) str

Creates the HTML sections containing optional analyses.

fuzz_introspector.html_report.get_body_script_tags() str

Add relevant <script> tag at the end of the body.

fuzz_introspector.html_report.write_content_to_html_files(html_full_doc, all_functions_json_html, fuzzer_table_data)

Writes the content of the HTML static website to the relevant files.

Parameters:
  • html_full_doc – content of the main fuzz_report.html file

  • all_functions_json_html – dictionary in json format for all functions in the all functions table. These will be written ot a javascript file that is then loaded dynamically in the browser to reduce overhead of loading it all by way of hte .html file.

  • fuzzer_table_data – data for tables for each fuzzer, in the detailed fuzzer section. To be written in a javascript file that is loaded dynamically.

fuzz_introspector.utils

Utility functions

fuzz_introspector.utils.data_file_read_yaml(filename: str) Optional[Dict[Any, Any]]

Reads a file as a yaml file. This is used to load data from fuzz-introspectors compiler plugin output.

fuzz_introspector.utils.demangle_jvm_func(package: str, funcname: str) str

Add package class name to uniquly identify jvm functons

fuzz_introspector.utils.get_all_files_in_tree_with_regex(basedir: str, regex_str: str) List[str]

Returns a list of paths such that each path is to a file with the provided suffix. Walks the entire tree of basedir.

fuzz_introspector.utils.get_target_coverage_url(coverage_url: str, target_name: str, target_lang: str) str
This function changes overall coverage URL to per-target coverage URL. Like:

https://storage.googleapis.com/oss-fuzz-coverage/<project>/reports/<report-date>/linux to https://storage.googleapis.com/oss-fuzz-coverage/<project>/reports-by-target/<report-date>/<target-name>/linux

fuzz_introspector.utils.group_path_list_by_target(list: List[List[Any]]) Dict[Any, List[Any]]

Group path list items by path target which is the last itme of each list.

fuzz_introspector.utils.load_func_names(input_list: List[str], check_for_blocking: bool = True) List[str]

Takes a list of function names (typically from llvm profile) and makes sure the output names are demangled.

fuzz_introspector.utils.longest_common_prefix(strs: List[str]) str

Dummy wrapper function for os.path.commonpath(paths: List[str]) -> str Keeping for backward compactibility

Resolves link to HTML coverage report

fuzz_introspector.utils.scan_executables_for_fuzz_introspector_logs(exec_dir: str) List[Dict[str, str]]

Finds all executables containing fuzzerLogFile string

Args:

exec_dir: Directory in which to search for executables.

Returns:

A list of dictionaries where each dictionary contains data about an executable that contains fuzzerLogFile string.