Skip to content

Commit

Permalink
report: add numeric represntation of calltree
Browse files Browse the repository at this point in the history
Fixes: ossf#406
  • Loading branch information
DavidKorczynski committed Jul 29, 2022
1 parent 011ea59 commit 19e5906
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
9 changes: 2 additions & 7 deletions src/fuzz_introspector/analysis.py
Expand Up @@ -28,6 +28,7 @@
)

from fuzz_introspector import utils
from fuzz_introspector import constants
from fuzz_introspector import cfg_load
from fuzz_introspector import code_coverage
from fuzz_introspector import html_helpers
Expand Down Expand Up @@ -254,13 +255,7 @@ def callstack_set_curr_node(

# Map hitcount to color of target.
def get_hit_count_color(hit_count: int) -> str:
color_schemes = [
(0, 1, "red"),
(1, 10, "gold"),
(10, 30, "yellow"),
(30, 50, "greenyellow"),
(50, 1000000000000, "lawngreen")]
for cmin, cmax, cname in color_schemes:
for cmin, cmax, cname, rgb in constants.COLOR_CONSTANTS:
if hit_count >= cmin and hit_count < cmax:
return cname
return "red"
Expand Down
16 changes: 16 additions & 0 deletions src/fuzz_introspector/constants.py
Expand Up @@ -22,3 +22,19 @@
APP_EXIT_SUCCESS = 0

INPUT_BUG_FILE = "input_bugs.json"

# Color constants used for call trees. Composed of tuples,
# (min, max, color) where
# min and max construct an interval [min: max) (max non-inclusive)
# and this interval indicates how many times a callsite was hit. If a
# callsite is hit X times and X falls in the given interval then it will
# have the color of the tuple.
# - color is the string
# The hitcount is [min:max)
COLOR_CONSTANTS = [
(0, 1, "red", "#ff0000"),
(1, 10, "gold", "#ffd700"),
(10, 30, "yellow", "#ffff00"),
(30, 50, "greenyellow", "#adff2f"),
(50, 1000000000000, "lawngreen", "#7cfc00")
]
65 changes: 55 additions & 10 deletions src/fuzz_introspector/html_report.py
Expand Up @@ -46,7 +46,7 @@
def create_horisontal_calltree_image(
image_name: str,
profile: fuzzer_profile.FuzzerProfile
) -> None:
) -> 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
Expand All @@ -56,7 +56,8 @@ def create_horisontal_calltree_image(
logger.info(f"Creating image {image_name}")

if profile.function_call_depths is None:
return
return []

# Extract color sequence
color_list: List[str] = []
for node in cfg_load.extract_all_callsites(profile.function_call_depths):
Expand Down Expand Up @@ -116,6 +117,7 @@ def create_horisontal_calltree_image(
fig.tight_layout()
fig.savefig(image_name, bbox_extra_artists=[xlabel])
logger.info("- image saved")
return color_list


def create_overview_table(
Expand Down Expand Up @@ -498,13 +500,26 @@ def create_fuzzer_detailed_section(
f"The following is the call tree with color coding for which "
f"functions are hit/not hit. This info is based on the coverage "
f"achieved of all fuzzers together and not just this specific "
f"fuzzer."
f"</p>"
f"<p><ul>"
f"<li>Red: no hits</li>"
f"<li>Yellow: few hits</li>"
f"<li>Green: many hits</li>"
f"</ul></p>"
f"fuzzer. We use the following coloring scheme where min/max is "
f"an interval [min:max) (max non-inclusive) to color the callsite "
f"based on how many times the callsite is covered at run time."
)
html_string += (
"<table><tr><th>Min</th>"
"<th style=\"text-align: left;\">Max</th>"
"<th style=\"text-align: left;\">Color</th></tr>"
)
for _min, _max, color, rgb_code in constants.COLOR_CONSTANTS:
html_string += "<tr>"
html_string += f"<td style=\"text-align: left;\">{_min}</td><td>{_max}</td>"
html_string += (
f"<td style=\"color:{color}; "
f"text-shadow: -1px 0 black, 0 1px black, "
f"1px 0 black, 0 -1px black;\"><b>{color}</b></td>"
)
html_string += "</tr>"
html_string += "</table></p>"
html_string += (
f"<p>"
f"For further technical details on the call tree overview"
f", please see the <a href=\"{constants.GIT_BRANCH_URL}/doc/"
Expand All @@ -517,8 +532,38 @@ def create_fuzzer_detailed_section(
colormap_file_prefix = colormap_file_prefix.replace("/", "_")
image_name = f"{colormap_file_prefix}_colormap.png"

create_horisontal_calltree_image(image_name, profile)
color_list = create_horisontal_calltree_image(image_name, profile)
html_string += f"<img class=\"colormap\" src=\"{image_name}\">"
color_dictionary = {
"red": 0,
"gold": 0,
"yellow": 0,
"greenyellow": 0,
"lawngreen": 0
}
for color in color_list:
color_dictionary[color] = color_dictionary[color] + 1
html_string += (
"<p>The distribution of callsites in terms of hit count is"
)

html_string += (
"<table><tr>"
"<th style=\"text-align: left;\">Color</th>"
"<th style=\"text-align: left;\">Callsite count</th></tr>"
)
for _min, _max, color, rgb_code in constants.COLOR_CONSTANTS:
html_string += (
f"<tr><td style=\"color:{color}; "
f"text-shadow: -1px 0 black, 0 1px black, "
f"1px 0 black, 0 -1px black;\"><b>{color}</b></td>"
)
html_string += f"<td>{color_dictionary[color]}</td></tr>"

# Add a row with total amount of callsites
html_string += f"<tr><td>All colors</td><td>{len(color_list)}</td></tr>"
html_string += "</table>"
html_string += "</p>"

# Full calltree
html_string += html_helpers.html_add_header_with_link(
Expand Down

0 comments on commit 19e5906

Please sign in to comment.