Coverage for /pythoncovmergedfiles/medio/medio/src/gitpython/fuzzing/fuzz-targets/utils.py: 78%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

50 statements  

1import atheris # pragma: no cover 

2import os # pragma: no cover 

3import re # pragma: no cover 

4import traceback # pragma: no cover 

5import sys # pragma: no cover 

6from typing import Set, Tuple, List # pragma: no cover 

7 

8 

9@atheris.instrument_func 

10def is_expected_exception_message(exception: Exception, error_message_list: List[str]) -> bool: # pragma: no cover 

11 """ 

12 Checks if the message of a given exception matches any of the expected error messages, case-insensitively. 

13 

14 Args: 

15 exception (Exception): The exception object raised during execution. 

16 error_message_list (List[str]): A list of error message substrings to check against the exception's message. 

17 

18 Returns: 

19 bool: True if the exception's message contains any of the substrings from the error_message_list, 

20 case-insensitively, otherwise False. 

21 """ 

22 exception_message = str(exception).lower() 

23 for error in error_message_list: 

24 if error.lower() in exception_message: 

25 return True 

26 return False 

27 

28 

29@atheris.instrument_func 

30def get_max_filename_length(path: str) -> int: # pragma: no cover 

31 """ 

32 Get the maximum filename length for the filesystem containing the given path. 

33 

34 Args: 

35 path (str): The path to check the filesystem for. 

36 

37 Returns: 

38 int: The maximum filename length. 

39 """ 

40 return os.pathconf(path, "PC_NAME_MAX") 

41 

42 

43@atheris.instrument_func 

44def read_lines_from_file(file_path: str) -> list: 

45 """Read lines from a file and return them as a list.""" 

46 try: 

47 with open(file_path, "r") as f: 

48 return [line.strip() for line in f if line.strip()] 

49 except FileNotFoundError: 

50 print(f"File not found: {file_path}") 

51 return [] 

52 except IOError as e: 

53 print(f"Error reading file {file_path}: {e}") 

54 return [] 

55 

56 

57@atheris.instrument_func 

58def load_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 for line in lines: 

66 match = re.match(r"(.+):(\d+):", line) 

67 if match: 

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 return exception_list 

72 except Exception as e: 

73 print(f"Error loading exception list: {e}") 

74 return set() 

75 

76 

77@atheris.instrument_func 

78def match_exception_with_traceback(exception_list: Set[Tuple[str, str]], exc_traceback) -> bool: 

79 """Match exception traceback with the entries in the exception list.""" 

80 for filename, lineno, _, _ in traceback.extract_tb(exc_traceback): 

81 for file_pattern, line_pattern in exception_list: 

82 # Ensure filename and line_number are strings for regex matching 

83 if re.fullmatch(file_pattern, filename) and re.fullmatch(line_pattern, str(lineno)): 

84 return True 

85 return False 

86 

87 

88@atheris.instrument_func 

89def check_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 return match_exception_with_traceback(exception_list, exc_traceback) 

93 

94 

95@atheris.instrument_func 

96def handle_exception(e: Exception) -> int: 

97 """Encapsulate exception handling logic for reusability.""" 

98 exc_traceback = e.__traceback__ 

99 if check_exception_against_list(exc_traceback): 

100 return -1 

101 else: 

102 raise e 

103 

104 

105@atheris.instrument_func 

106def setup_git_environment() -> None: 

107 """Set up the environment variables for Git.""" 

108 bundle_dir = os.path.dirname(os.path.abspath(__file__)) 

109 if getattr(sys, "frozen", False) and hasattr(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 if not sys.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 import warnings 

117 import logging 

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)