|
1 | 1 | importatheris# pragma: no cover |
2 | 2 | importos# pragma: no cover |
3 | | -fromtypingimportList# pragma: no cover |
| 3 | +importre# pragma: no cover |
| 4 | +importtraceback# pragma: no cover |
| 5 | +importsys# pragma: no cover |
| 6 | +fromtypingimportSet,Tuple,List# pragma: no cover |
4 | 7 |
|
5 | 8 |
|
6 | 9 | @atheris.instrument_func |
@@ -35,3 +38,85 @@ def get_max_filename_length(path: str) -> int: # pragma: no cover |
35 | 38 | int: The maximum filename length. |
36 | 39 | """ |
37 | 40 | returnos.pathconf(path,"PC_NAME_MAX") |
| 41 | + |
| 42 | + |
| 43 | +@atheris.instrument_func |
| 44 | +defread_lines_from_file(file_path:str)->list: |
| 45 | +"""Read lines from a file and return them as a list.""" |
| 46 | +try: |
| 47 | +withopen(file_path,"r")asf: |
| 48 | +return [line.strip()forlineinfifline.strip()] |
| 49 | +exceptFileNotFoundError: |
| 50 | +print(f"File not found:{file_path}") |
| 51 | +return [] |
| 52 | +exceptIOErrorase: |
| 53 | +print(f"Error reading file{file_path}:{e}") |
| 54 | +return [] |
| 55 | + |
| 56 | + |
| 57 | +@atheris.instrument_func |
| 58 | +defload_exception_list(file_path:str="explicit-exceptions-list.txt")->Set[Tuple[str,str]]: |
| 59 | +"""Load and parse the exception list from a default or specified file.""" |
| 60 | +try: |
| 61 | +bundle_dir=os.path.dirname(os.path.abspath(__file__)) |
| 62 | +full_path=os.path.join(bundle_dir,file_path) |
| 63 | +lines=read_lines_from_file(full_path) |
| 64 | +exception_list:Set[Tuple[str,str]]=set() |
| 65 | +forlineinlines: |
| 66 | +match=re.match(r"(.+):(\d+):",line) |
| 67 | +ifmatch: |
| 68 | +file_path:str=match.group(1).strip() |
| 69 | +line_number:str=str(match.group(2).strip()) |
| 70 | +exception_list.add((file_path,line_number)) |
| 71 | +returnexception_list |
| 72 | +exceptExceptionase: |
| 73 | +print(f"Error loading exception list:{e}") |
| 74 | +returnset() |
| 75 | + |
| 76 | + |
| 77 | +@atheris.instrument_func |
| 78 | +defmatch_exception_with_traceback(exception_list:Set[Tuple[str,str]],exc_traceback)->bool: |
| 79 | +"""Match exception traceback with the entries in the exception list.""" |
| 80 | +forfilename,lineno,_,_intraceback.extract_tb(exc_traceback): |
| 81 | +forfile_pattern,line_patterninexception_list: |
| 82 | +# Ensure filename and line_number are strings for regex matching |
| 83 | +ifre.fullmatch(file_pattern,filename)andre.fullmatch(line_pattern,str(lineno)): |
| 84 | +returnTrue |
| 85 | +returnFalse |
| 86 | + |
| 87 | + |
| 88 | +@atheris.instrument_func |
| 89 | +defcheck_exception_against_list(exc_traceback,exception_file:str="explicit-exceptions-list.txt")->bool: |
| 90 | +"""Check if the exception traceback matches any entry in the exception list.""" |
| 91 | +exception_list=load_exception_list(exception_file) |
| 92 | +returnmatch_exception_with_traceback(exception_list,exc_traceback) |
| 93 | + |
| 94 | + |
| 95 | +@atheris.instrument_func |
| 96 | +defhandle_exception(e:Exception)->int: |
| 97 | +"""Encapsulate exception handling logic for reusability.""" |
| 98 | +exc_traceback=e.__traceback__ |
| 99 | +ifcheck_exception_against_list(exc_traceback): |
| 100 | +return-1 |
| 101 | +else: |
| 102 | +raisee |
| 103 | + |
| 104 | + |
| 105 | +@atheris.instrument_func |
| 106 | +defsetup_git_environment()->None: |
| 107 | +"""Set up the environment variables for Git.""" |
| 108 | +bundle_dir=os.path.dirname(os.path.abspath(__file__)) |
| 109 | +ifgetattr(sys,"frozen",False)andhasattr(sys,"_MEIPASS"):# pragma: no cover |
| 110 | +bundled_git_binary_path=os.path.join(bundle_dir,"git") |
| 111 | +os.environ["GIT_PYTHON_GIT_EXECUTABLE"]=bundled_git_binary_path |
| 112 | + |
| 113 | +ifnotsys.warnoptions:# pragma: no cover |
| 114 | +# The warnings filter below can be overridden by passing the -W option |
| 115 | +# to the Python interpreter command line or setting the `PYTHONWARNINGS` environment variable. |
| 116 | +importwarnings |
| 117 | +importlogging |
| 118 | + |
| 119 | +# Fuzzing data causes some modules to generate a large number of warnings |
| 120 | +# which are not usually interesting and make the test output hard to read, so we ignore them. |
| 121 | +warnings.simplefilter("ignore") |
| 122 | +logging.getLogger().setLevel(logging.ERROR) |