Coverage for /pythoncovmergedfiles/medio/medio/src/gitpython/fuzzing/fuzz-targets/fuzz_submodule.py: 59%
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
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
1###### Coverage stub
2import atexit
3import coverage
4cov = coverage.coverage(data_file='.coverage', cover_pylib=True)
5cov.start()
6# Register an exist handler that will print coverage
7def exit_handler():
8 cov.stop()
9 cov.save()
10atexit.register(exit_handler)
11####### End of coverage stub
12import atheris
13import sys
14import os
15import tempfile
16from configparser import ParsingError
17from utils import (
18 setup_git_environment,
19 handle_exception,
20 get_max_filename_length,
21)
23# Setup the Git environment
24setup_git_environment()
25from git import Repo, GitCommandError, InvalidGitRepositoryError
28def sanitize_input(input_str, max_length=255):
29 """Sanitize and truncate inputs to avoid invalid Git operations."""
30 sanitized = "".join(ch for ch in input_str if ch.isalnum() or ch in ("-", "_", "."))
31 return sanitized[:max_length]
34def TestOneInput(data):
35 fdp = atheris.FuzzedDataProvider(data)
37 with tempfile.TemporaryDirectory() as repo_temp_dir:
38 repo = Repo.init(path=repo_temp_dir)
39 repo.index.commit("Initial commit")
41 try:
42 with tempfile.TemporaryDirectory() as submodule_temp_dir:
43 sub_repo = Repo.init(submodule_temp_dir, bare=fdp.ConsumeBool())
44 commit_message = sanitize_input(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 512)))
45 sub_repo.index.commit(commit_message)
47 submodule_name = sanitize_input(
48 fdp.ConsumeUnicodeNoSurrogates(
49 fdp.ConsumeIntInRange(1, get_max_filename_length(repo.working_tree_dir))
50 )
51 )
53 submodule_path = os.path.relpath(
54 os.path.join(repo.working_tree_dir, submodule_name),
55 start=repo.working_tree_dir,
56 )
58 # Ensure submodule_path is valid
59 if not submodule_name or submodule_name.startswith("/") or ".." in submodule_name:
60 return -1 # Reject invalid input so they are not added to the corpus
62 submodule = repo.create_submodule(submodule_name, submodule_path, url=sub_repo.git_dir)
63 repo.index.commit("Added submodule")
65 with submodule.config_writer() as writer:
66 key_length = fdp.ConsumeIntInRange(1, max(1, fdp.remaining_bytes()))
67 value_length = fdp.ConsumeIntInRange(1, max(1, fdp.remaining_bytes()))
69 writer.set_value(
70 sanitize_input(fdp.ConsumeUnicodeNoSurrogates(key_length)),
71 sanitize_input(fdp.ConsumeUnicodeNoSurrogates(value_length)),
72 )
73 writer.release()
75 submodule.update(
76 init=fdp.ConsumeBool(),
77 dry_run=fdp.ConsumeBool(),
78 force=fdp.ConsumeBool(),
79 )
81 submodule_repo = submodule.module()
83 new_file_name = sanitize_input(
84 fdp.ConsumeUnicodeNoSurrogates(
85 fdp.ConsumeIntInRange(1, get_max_filename_length(submodule_repo.working_tree_dir))
86 )
87 )
88 new_file_path = os.path.join(submodule_repo.working_tree_dir, new_file_name)
89 with open(new_file_path, "wb") as new_file:
90 new_file.write(fdp.ConsumeBytes(fdp.ConsumeIntInRange(1, 512)))
92 submodule_repo.index.add([new_file_path])
93 submodule_repo.index.commit("Added new file to submodule")
95 repo.submodule_update(recursive=fdp.ConsumeBool())
96 submodule_repo.head.reset(
97 commit="HEAD~1",
98 working_tree=fdp.ConsumeBool(),
99 head=fdp.ConsumeBool(),
100 )
102 module_option_value, configuration_option_value = fdp.PickValueInList(
103 [(True, False), (False, True), (True, True)]
104 )
105 submodule.remove(
106 module=module_option_value,
107 configuration=configuration_option_value,
108 dry_run=fdp.ConsumeBool(),
109 force=fdp.ConsumeBool(),
110 )
111 repo.index.commit(f"Removed submodule {submodule_name}")
113 except (
114 ParsingError,
115 GitCommandError,
116 InvalidGitRepositoryError,
117 FileNotFoundError,
118 FileExistsError,
119 IsADirectoryError,
120 NotADirectoryError,
121 BrokenPipeError,
122 PermissionError,
123 ):
124 return -1
125 except Exception as e:
126 return handle_exception(e)
129def main():
130 atheris.instrument_all()
131 atheris.Setup(sys.argv, TestOneInput)
132 atheris.Fuzz()
135if __name__ == "__main__":
136 main()