From e09e740103c0d1c0e392bb6a1e91103955681213 Mon Sep 17 00:00:00 2001 From: David Korczynski Date: Wed, 1 Jun 2022 16:57:31 +0100 Subject: [PATCH 1/2] post-process: substitute exits for exceptions The post-processing logic is getting larger and makes sense to make it more Pythonian. Switching calls to exit for python exceptions to support this. --- post-processing/exceptions.py | 26 ++++++++++++++++++++++++++ post-processing/fuzz_analysis.py | 10 ++++++++-- post-processing/fuzz_cfg_load.py | 5 ++++- post-processing/fuzz_data_loader.py | 6 +++++- 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 post-processing/exceptions.py diff --git a/post-processing/exceptions.py b/post-processing/exceptions.py new file mode 100644 index 000000000..1ec14835b --- /dev/null +++ b/post-processing/exceptions.py @@ -0,0 +1,26 @@ +# Copyright 2022 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Exceptions used throughout the package.""" + +class FuzzIntrospectorError(Exception): + """Base error""" + +class CalltreeError(FuzzIntrospectorError): + """Error for when dealing with calltrees""" + +class AnalysisError(FuzzIntrospectorError): + """Error for analysis logic""" + +class DataLoaderError(FuzzIntrospectorError): + """Error for handling data loader issues""" diff --git a/post-processing/fuzz_analysis.py b/post-processing/fuzz_analysis.py index e6c8ca9f6..ebfddba38 100644 --- a/post-processing/fuzz_analysis.py +++ b/post-processing/fuzz_analysis.py @@ -29,6 +29,8 @@ import fuzz_data_loader from enum import Enum +from exceptions import AnalysisError + logger = logging.getLogger(name=__name__) logger.setLevel(logging.INFO) @@ -142,7 +144,9 @@ def callstack_set_curr_node(n, name, c): if demangled_name != "LLVMFuzzerTestOneInput" and "TestOneInput" not in demangled_name: logger.info("Unexpected first node in the calltree.") logger.info(f"Found: {demangled_name}") - exit(1) + raise AnalysisError( + "First node in calltree seems to be non-fuzzer function" + ) coverage_data = profile.coverage.get_hit_details("LLVMFuzzerTestOneInput") if len(coverage_data) == 0: logger.error("There is no coverage data (not even all negative).") @@ -165,7 +169,9 @@ def callstack_set_curr_node(n, name, c): node.cov_parent = callstack_get_parent(node, callstack) else: logger.error("A node should either be the first or it must have a parent") - exit(1) + raise AnalysisError( + "A node should either be the first or it must have a parent" + ) node.cov_hitcount = node_hitcount # Map hitcount to color of target. diff --git a/post-processing/fuzz_cfg_load.py b/post-processing/fuzz_cfg_load.py index 67a8b901c..ae90060a9 100644 --- a/post-processing/fuzz_cfg_load.py +++ b/post-processing/fuzz_cfg_load.py @@ -20,6 +20,8 @@ Optional ) +from exceptions import CalltreeError + logger = logging.getLogger(name=__name__) @@ -72,7 +74,8 @@ def extract_all_callsites_recursive( def extract_all_callsites(calltree: Optional[CalltreeCallsite]) -> List[CalltreeCallsite]: if calltree is None: logger.error("Trying to extract from a None calltree") - exit(1) + raise CalltreeError("Calltree is None") + cs_list: List[CalltreeCallsite] = [] extract_all_callsites_recursive(calltree, cs_list) return cs_list diff --git a/post-processing/fuzz_data_loader.py b/post-processing/fuzz_data_loader.py index 6c2736746..ef065b84c 100644 --- a/post-processing/fuzz_data_loader.py +++ b/post-processing/fuzz_data_loader.py @@ -32,6 +32,8 @@ import fuzz_cov_load import fuzz_utils +from exceptions import DataLoaderError + logger = logging.getLogger(name=__name__) logger.setLevel(logging.INFO) @@ -652,7 +654,9 @@ def add_func_to_reached_and_clone(merged_profile_old: MergedProjectProfile, if merged_profile.all_functions[func_to_add.function_name].hitcount == 0: logger.info("Error. Hitcount did not get set for some reason. Exiting") - exit(1) + raise DataLoaderError( + "Hitcount did not get set for some reason" + ) return merged_profile From 876febf803d281117bbd4ab07189b16d2724b279 Mon Sep 17 00:00:00 2001 From: David Korczynski Date: Wed, 1 Jun 2022 17:07:25 +0100 Subject: [PATCH 2/2] nit --- post-processing/exceptions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/post-processing/exceptions.py b/post-processing/exceptions.py index 1ec14835b..925ff57f1 100644 --- a/post-processing/exceptions.py +++ b/post-processing/exceptions.py @@ -13,14 +13,18 @@ # limitations under the License. """Exceptions used throughout the package.""" + class FuzzIntrospectorError(Exception): """Base error""" + class CalltreeError(FuzzIntrospectorError): """Error for when dealing with calltrees""" + class AnalysisError(FuzzIntrospectorError): """Error for analysis logic""" + class DataLoaderError(FuzzIntrospectorError): """Error for handling data loader issues"""