2
0

fuzz_repo.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  2. import os
  3. import sys
  4. import tempfile
  5. from typing import Optional
  6. import atheris
  7. with atheris.instrument_imports():
  8. # We instrument `test_utils` as well, so it doesn't block coverage analysis in Fuzz Introspector:
  9. from test_utils import EnhancedFuzzedDataProvider, is_expected_exception
  10. from dulwich.repo import (
  11. InvalidUserIdentity,
  12. Repo,
  13. )
  14. def TestOneInput(data) -> Optional[int]:
  15. fdp = EnhancedFuzzedDataProvider(data)
  16. with tempfile.TemporaryDirectory() as temp_dir:
  17. repo = Repo.init(temp_dir)
  18. repo.set_description(fdp.ConsumeRandomBytes())
  19. repo.get_description()
  20. try:
  21. # Generate a minimal set of files based on fuzz data to minimize I/O operations.
  22. file_names = [
  23. f"File{i}{fdp.ConsumeRandomString(without_surrogates=True)}"
  24. for i in range(min(3, fdp.ConsumeIntInRange(1, 3)))
  25. ]
  26. for file in file_names:
  27. with open(os.path.join(temp_dir, file), "wb") as f:
  28. f.write(fdp.ConsumeRandomBytes())
  29. except (ValueError, OSError):
  30. # Exit early if the fuzzer generates an invalid filename.
  31. return -1
  32. try:
  33. repo.stage(file_names)
  34. repo.do_commit(
  35. message=fdp.ConsumeRandomBytes(),
  36. committer=fdp.ConsumeRandomBytes(),
  37. author=fdp.ConsumeRandomBytes(),
  38. commit_timestamp=fdp.ConsumeRandomInt(),
  39. commit_timezone=fdp.ConsumeRandomInt(),
  40. author_timestamp=fdp.ConsumeRandomInt(),
  41. author_timezone=fdp.ConsumeRandomInt(),
  42. )
  43. except InvalidUserIdentity:
  44. return -1
  45. except ValueError as e:
  46. if is_expected_exception(["Unable to handle non-minute offset"], e):
  47. return -1
  48. else:
  49. raise e
  50. def main() -> None:
  51. atheris.Setup(sys.argv, TestOneInput)
  52. atheris.Fuzz()
  53. if __name__ == "__main__":
  54. main()