Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JVM issue] Fix link bug #640

Merged
merged 6 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions oss_fuzz_integration/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,29 @@ def patch_jvm_source_dead_link(server_directory, prefix):
source report format and those links will be dead. This patch aim
to check all those link and disable them if the link is dead.
"""
# Patch dead link in fuzz_report.html (stored in all_functions.js / analysis_1.js)
# Patch dead link in fuzz_report.html (stored in js files)
print("Start patching dead link in fuzz_report.html")

files = ["all_functions.js", "analysis_1.js"]
for file in files:
# Read js file
with open(os.path.join(server_directory, file)) as f:
report = f.read()

# Replace dead link with '#'
links = re.findall(r'href=[\'"]?([^\'" >]+)', report)
links.extend(re.findall(r'[\'"]func_url[\'"]:\ [\'"]?([^\'" >]+)', report))
for link in links:
if link.startswith(prefix) and not os.path.exists(link[1:].split("#")[0]):
report = report.replace(link, "#")

# Write result back to js file
with open(os.path.join(server_directory, file), "w+") as f:
f.write(report)
for root, _, files in os.walk(os.path.abspath(server_directory)):
for file in files:
if file.endswith(".js"):

# Read js file
with open(os.path.join(root, file)) as f:
report = f.read()

# Replace dead link with '#'
links = re.findall(r'href=[\'"]?([^\'" >]+)', report)
links.extend(re.findall(r'[\'"]func_url[\'"]:\ [\'"]?([^\'" >]+)', report))
for link in links:
if link.startswith(prefix) and not os.path.exists(
os.path.join(server_directory, link[1:].split("#")[0])
):
report = report.replace(link, "#")

# Write result back to js file
with open(os.path.join(root, file), "w+") as f:
f.write(report)

print("Finish patching dead link in fuzz_Report.html")

Expand Down
12 changes: 8 additions & 4 deletions src/fuzz_introspector/analyses/optimal_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def analysis_func(
optimal_target_functions,
toc_list,
tables,
coverage_url
coverage_url,
profiles[0].target_lang
)

# Create section for how the state of the project will be if
Expand Down Expand Up @@ -224,7 +225,8 @@ def get_optimal_target_section(
optimal_target_functions: List[function_profile.FunctionProfile],
toc_list: List[Tuple[str, str, int]],
tables: List[str],
coverage_url: str
coverage_url: str,
target_lang: str = 'c-cpp'
) -> str:
# Table with details about optimal target functions
html_string = html_helpers.html_add_header_with_link(
Expand Down Expand Up @@ -257,10 +259,12 @@ def get_optimal_target_section(
]
)
for fd in optimal_target_functions:
func_cov_url = "%s%s.html#L%d" % (
func_cov_url = utils.resolve_coverage_link(
coverage_url,
fd.function_source_file,
fd.function_linenumber
fd.function_linenumber,
fd.function_name,
target_lang
)
html_func_row = (
f"<a href=\"{ func_cov_url }\"><code class='language-clike'>"
Expand Down
93 changes: 7 additions & 86 deletions src/fuzz_introspector/datatypes/fuzzer_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"""Fuzzer profile"""

import os
import json
import logging

from typing import (
Expand Down Expand Up @@ -135,30 +134,13 @@ def resolve_coverage_link(
function_name: str
) -> str:
"""Resolves a link to a coverage report."""
if self.target_lang == "c-cpp":
return self._resolve_c_cpp_coverage_link(
cov_url,
source_file,
lineno,
function_name
)
elif self.target_lang == "python":
return self._resolve_python_coverage_link(
cov_url,
source_file,
lineno,
function_name
)
elif self.target_lang == "jvm":
return self._resolve_jvm_coverage_link(
cov_url,
source_file,
lineno,
function_name
)
else:
logger.info("Could not find any html_status.json file")
return "#"
return utils.resolve_coverage_link(
cov_url,
source_file,
lineno,
function_name,
self.target_lang
)

def refine_paths(self, basefolder: str) -> None:
"""Iterate over source files in the calltree and file_targets and remove
Expand Down Expand Up @@ -525,64 +507,3 @@ def _is_func_name_missing_normalisation(self, func_name: str) -> bool:
if split_name[-1].isnumeric():
return True
return False

def _resolve_c_cpp_coverage_link(
self,
cov_url: str,
source_file: str,
lineno: int,
function_name: str
) -> str:
"""Resolves link to HTML coverage report for C/CPP targets"""
return cov_url + source_file + ".html#L" + str(lineno)

def _resolve_python_coverage_link(
self,
cov_url: str,
source_file: str,
lineno: int,
function_name: str
) -> str:
"""Resolves link to HTML coverage report for Python targets"""
# Temporarily for debugging purposes. TODO: David remove this later
# Find the html_status.json file. This is a file generated by the Python
# coverate utility and contains mappings from source to html file. We
# need this mapping in order to create links from the data extracted
# during AST analysis, as there we only have the source code.
html_summaries = utils.get_all_files_in_tree_with_regex(".", ".*html_status.json$")
logger.debug(str(html_summaries))
if len(html_summaries) > 0:
html_idx = html_summaries[0]
with open(html_idx, "r") as jf:
data = json.load(jf)
for fl in data['files']:
found_target = utils.approximate_python_coverage_files(
function_name,
data['files'][fl]['index']['relative_filename'],
)
if found_target:
return cov_url + "/" + fl + ".html" + "#t" + str(lineno)
else:
logger.info("Could not find any html_status.json file")
return "#"

def _resolve_jvm_coverage_link(
self,
cov_url: str,
source_file: str,
lineno: int,
function_name: str
) -> str:
"""Resolves link to HTML coverage report for JVM targets"""
# Handle source class for jvm
if ("." in source_file):
# Source file has package, change package.class to package/class
source_file = os.sep.join(source_file.rsplit(".", 1))
else:
# Source file has no package, add in default package
source_file = os.path.join("default", source_file)

# Handle subclass definition in the same source file
source_file = source_file.split("$")[0]

return cov_url + os.sep + source_file + ".java.html#L" + str(lineno)
52 changes: 52 additions & 0 deletions src/fuzz_introspector/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,55 @@ def load_func_names(
continue
loaded.append(demangle_cpp_func(reached))
return loaded


def resolve_coverage_link(
cov_url: str,
source_file: str,
lineno: int,
function_name: str,
target_lang: str
) -> str:
"""Resolves link to HTML coverage report"""
if (target_lang == "c-cpp"):
return cov_url + source_file + ".html#L" + str(lineno)
elif (target_lang == "python"):
"""Resolves link to HTML coverage report for Python targets"""
# Temporarily for debugging purposes. TODO: David remove this later
# Find the html_status.json file. This is a file generated by the Python
# coverate utility and contains mappings from source to html file. We
# need this mapping in order to create links from the data extracted
# during AST analysis, as there we only have the source code.
html_summaries = get_all_files_in_tree_with_regex(".", ".*html_status.json$")
logger.debug(str(html_summaries))
if len(html_summaries) > 0:
html_idx = html_summaries[0]
with open(html_idx, "r") as jf:
data = json.load(jf)
for fl in data['files']:
found_target = approximate_python_coverage_files(
function_name,
data['files'][fl]['index']['relative_filename'],
)
if found_target:
return cov_url + "/" + fl + ".html" + "#t" + str(lineno)
else:
logger.info("Could not find any html_status.json file")
return "#"
elif (target_lang == "jvm"):
"""Resolves link to HTML coverage report for JVM targets"""
# Handle source class for jvm
if ("." in source_file):
# Source file has package, change package.class to package/class
source_file = os.sep.join(source_file.rsplit(".", 1))
else:
# Source file has no package, add in default package
source_file = os.path.join("default", source_file)

# Handle subclass definition in the same source file
source_file = source_file.split("$")[0]

return cov_url + os.sep + source_file + ".java.html#L" + str(lineno)
else:
logger.info("Unsupported language for coverage link resolve")
return "#"