fuzz_repo.py 1.9 KB

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