Skip to content

Commit

Permalink
Fix logic
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Chan <[email protected]>
  • Loading branch information
arthurscchan committed Jan 20, 2025
1 parent 34ae096 commit 8587f60
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/fuzz_introspector/analyses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
metadata.MetadataAnalysis,
sinks_analyser.SinkCoverageAnalyser,
annotated_cfg.FuzzAnnotatedCFG,
source_code_line_analyser.SourceCodeLineFunctionAnalyser,
source_code_line_analyser.SourceCodeLineAnalyser,
]
45 changes: 39 additions & 6 deletions src/fuzz_introspector/analyses/source_code_line_analyser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""Analysis plugin for introspection of the function on target line in target source file."""

import os
import json
import logging

Expand All @@ -25,8 +26,8 @@
logger = logging.getLogger(name=__name__)


class SourceCodeLineFunctionAnalyser(analysis.AnalysisInterface):
name: str = 'SourceCodeLineFunctionAnalyser'
class SourceCodeLineAnalyser(analysis.AnalysisInterface):
name: str = 'SourceCodeLineAnalyser'

def __init__(self):
self.json_results: Dict[str, Any] = dict()
Expand Down Expand Up @@ -70,17 +71,49 @@ def analysis_func(self,
basefolder: str, coverage_url: str,
conclusions: List[html_helpers.HTMLConclusion],
out_dir) -> str:
logger.info(f" - Running analysis {self.get_name()}")
logger.info(self.properties)
logger.info(f' - Running analysis {self.get_name()}')

# Get target source file and line
target_source = self.properties.get('source_file')
target_line = self.properties.get('line')

if not target_source or not isinstance(target_line, int) or target_line <= 0:
logger.error('No valid source code or target line are provided')
return ''

# Get all functions from the profiles
all_functions = list(proj_profile.all_functions.values())
all_functions.extend(proj_profile.all_constructors.values())

# Generate a Source File to Function Profile map and store in JSON Result
func_file_map = {}
for function in all_functions:
func_list = self.json_results.get(function.function_source_file,
func_list = func_file_map.get(function.function_source_file_path,
[])
func_list.append(function)
self.json_results[function.function_source_file] = func_list
func_file_map[function.function_source_file_path] = func_list

if os.sep in target_source:
# File path
target_func_list = func_file_map.get(target_source, [])
else:
# File name
target_func_list = []
for key, value in func_file_map.items():
if os.path.basename(key) == target_source:
target_func_list.extend(value)

if not target_func_list:
logger.error('Failed to locate the target source file '
f'{target_source} from the project.')

result_list = []
for func in target_func_list:
if func.function_linenumber <= target_line <= func.function_line_number_end:
logger.info(f'Found function {func.function_name} from line {target_line} in {target_source}')
result_list.append(func)

if result_list:
self.json_results['functions'] = result_list

return ''
5 changes: 3 additions & 2 deletions src/fuzz_introspector/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
List,
Type,
Set,
Union
)

from fuzz_introspector import (cfg_load, code_coverage, constants, data_loader,
Expand Down Expand Up @@ -172,7 +173,7 @@ class AnalysisInterface(abc.ABC):
json_string_result: str = ""
display_html: bool = False

def set_additional_properties(self, properties: dict[str, str]):
def set_additional_properties(self, properties: dict[str, Union[str, int]]):
"""Allow setting additional properties for this analysis."""
self.properties = properties

Expand Down Expand Up @@ -235,7 +236,7 @@ def set_display_html(self, is_display_html):


def instantiate_analysis_interface(cls: Type[AnalysisInterface],
props: dict[str, str]):
props: dict[str, Union[str, int]]):
"""Wrapper function to satisfy Mypy semantics"""
analysis_interface = cls()
analysis_interface.set_additional_properties(props)
Expand Down
39 changes: 24 additions & 15 deletions src/fuzz_introspector/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Copyright 2024 Fuzz Introspector Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -19,6 +20,8 @@

from fuzz_introspector import commands, constants

from typing import Union

sys.setrecursionlimit(10000)

logger = logging.getLogger(name=__name__)
Expand Down Expand Up @@ -72,12 +75,16 @@ def get_cmdline_parser() -> argparse.ArgumentParser:
FuzzDriverSynthesizerAnalysis, FuzzEngineInputAnalysis,
FilePathAnalyser, ThirdPartyAPICoverageAnalyser,
MetadataAnalysis, OptimalTargets, RuntimeCoverageAnalysis,
SinkCoverageAnalyser, FunctionSourceLineAnalyser
SinkCoverageAnalyser, SourceCodeLineAnalyser
''')
full_parser.add_argument('--properties',
nargs='*',
default=[],
help='Additional properties for analysis')
full_parser.add_argument('--source-file',
default='',
type=str,
help='Target file path or name for SourceCodeLineAnalyser')
full_parser.add_argument('--line',
default=-1,
type=int,
help='Target line for SourceCodeLineAnalyser')

# Report generation command
report_parser = subparsers.add_parser(
Expand Down Expand Up @@ -106,7 +113,7 @@ def get_cmdline_parser() -> argparse.ArgumentParser:
FuzzDriverSynthesizerAnalysis, FuzzEngineInputAnalysis,
FilePathAnalyser, ThirdPartyAPICoverageAnalyser,
MetadataAnalysis, OptimalTargets, RuntimeCoverageAnalysis,
SinkCoverageAnalyser, FunctionSourceLineAnalyser
SinkCoverageAnalyser, SourceCodeLineAnalyser
""")
report_parser.add_argument("--enable-all-analyses",
action='store_true',
Expand All @@ -129,10 +136,14 @@ def get_cmdline_parser() -> argparse.ArgumentParser:
nargs="+",
default=["FuzzEngineInputAnalysis"],
help="State which analysis requires separate json report output")
report_parser.add_argument('--properties',
nargs='*',
default=[],
help='Additional properties for analysis')
report_parser.add_argument('--source-file',
default='',
type=str,
help='Target file path or name for SourceCodeLineAnalyser')
report_parser.add_argument('--line',
default=-1,
type=int,
help='Target line for SourceCodeLineAnalyser')

# Command for correlating binary files to fuzzerLog files
correlate_parser = subparsers.add_parser(
Expand Down Expand Up @@ -185,11 +196,9 @@ def main() -> int:

logger.info("Running fuzz introspector post-processing")
if args.command == 'report':
props: dict[str, str] = {}
for property in args.properties:
if property.count('=') == 1:
key, value = property.split('=', 1)
props[key] = value
props: dict[str, Union[str, int]] = {}
props['source_file'] = args.source_file
props['line'] = args.line

return_code = commands.run_analysis_on_dir(args.target_dir,
args.coverage_url,
Expand Down
19 changes: 10 additions & 9 deletions src/fuzz_introspector/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import json
import yaml
import shutil
from typing import List, Optional
from typing import Optional, Union

from fuzz_introspector import analysis
from fuzz_introspector import constants
Expand Down Expand Up @@ -54,6 +54,9 @@ def end_to_end(args) -> int:
else:
out_dir = os.getcwd()

if not os.path.exists(out_dir):
os.mkdir(out_dir)

if args.language == constants.LANGUAGES.JAVA:
entrypoint = 'fuzzerTestOneInput'
else:
Expand All @@ -69,11 +72,9 @@ def end_to_end(args) -> int:
else:
language = args.language

props: dict[str, str] = {}
for property in args.properties:
if property.count('=') == 1:
key, value = property.split('=', 1)
props[key] = value
props: dict[str, Union[str, int]] = {}
props['source_file'] = args.source_file
props['line'] = args.line

return run_analysis_on_dir(target_folder=out_dir,
coverage_url=args.coverage_url,
Expand All @@ -88,16 +89,16 @@ def end_to_end(args) -> int:

def run_analysis_on_dir(target_folder: str,
coverage_url: str,
analyses_to_run: List[str],
analyses_to_run: list[str],
correlation_file: str,
enable_all_analyses: bool,
report_name: str,
language: str,
output_json: Optional[List[str]] = None,
output_json: Optional[list[str]] = None,
parallelise: bool = True,
dump_files: bool = True,
out_dir: str = '',
props: dict[str, str] = {}) -> int:
props: dict[str, Union[str, int]] = {}) -> int:
"""Runs Fuzz Introspector analysis from based on the results
from a frontend run. The primary task is to aggregate the data
and generate a HTML report."""
Expand Down
4 changes: 4 additions & 0 deletions src/fuzz_introspector/datatypes/function_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ def __init__(self, elem: Dict[Any, Any]) -> None:
elem['BranchProfiles'])
self.signature = elem.get('signature', '')

# For backward compatibility on jvm project
# that the function_source_file stored the class name instead of file path.
self.function_source_file_path = elem.get('functionSourceFilePath', self.function_source_file)

# Duplication of functions_reached to keep the original sets
# of call trees for further processing and analysis. This
# could avoid loss of call tree information when functions_reached
Expand Down
4 changes: 4 additions & 0 deletions src/fuzz_introspector/frontends/frontend_jvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ def __init__(self,

# Store method line information
if self.is_default_constructor:
# print('FUCK')
# print(self.root.text.decode())
# print('ENDFUCK')
self.start_line = -1
self.end_line = -1
self.name = '<init>'
Expand Down Expand Up @@ -1045,6 +1048,7 @@ def dump_module_logic(self,
method_dict: dict[str, Any] = {}
method_dict['functionName'] = method.name
method_dict['functionSourceFile'] = method.class_interface.name
method_dict['functionSourceFilePath'] = method.parent_source.source_file
method_dict['functionLinenumber'] = method.start_line
method_dict['functionLinenumberEnd'] = method.end_line
method_dict['linkageType'] = ''
Expand Down
3 changes: 2 additions & 1 deletion src/fuzz_introspector/html_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
List,
Optional,
Tuple,
Union,
)

from fuzz_introspector import (analysis, constants, html_constants,
Expand Down Expand Up @@ -728,7 +729,7 @@ def create_html_report(introspection_proj: analysis.IntrospectionProject,
report_name,
dump_files,
out_dir: str = '',
props: dict[str, str] = {}) -> None:
props: dict[str, Union[str, int]] = {}) -> None:
"""
Logs a complete report. This is the current main place for looking at
data produced by fuzz introspector.
Expand Down

0 comments on commit 8587f60

Please sign in to comment.