fuzz_object_store.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import stat
  2. import sys
  3. from io import BytesIO
  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.errors import ObjectFormatException
  9. from dulwich.objects import S_IFGITLINK, Blob, Commit, Tree
  10. from dulwich.patch import write_tree_diff
  11. from dulwich.repo import (
  12. InvalidUserIdentity,
  13. MemoryRepo,
  14. )
  15. def TestOneInput(data):
  16. fdp = EnhancedFuzzedDataProvider(data)
  17. repo = MemoryRepo()
  18. blob = Blob.from_string(fdp.ConsumeRandomBytes())
  19. tree = Tree()
  20. tree.add(
  21. fdp.ConsumeRandomBytes(),
  22. fdp.PickValueInList([stat.S_IFREG, stat.S_IFLNK, stat.S_IFDIR, S_IFGITLINK]),
  23. blob.id,
  24. )
  25. commit = Commit()
  26. commit.tree = tree.id
  27. commit.author = fdp.ConsumeRandomBytes()
  28. commit.committer = fdp.ConsumeRandomBytes()
  29. commit.commit_time = fdp.ConsumeRandomInt()
  30. commit.commit_timezone = fdp.ConsumeRandomInt()
  31. commit.author_time = fdp.ConsumeRandomInt()
  32. commit.author_timezone = fdp.ConsumeRandomInt()
  33. commit.message = fdp.ConsumeRandomBytes()
  34. object_store = repo.object_store
  35. try:
  36. object_store.add_object(blob)
  37. object_store.add_object(tree)
  38. object_store.add_object(commit)
  39. except (InvalidUserIdentity, ObjectFormatException):
  40. return -1
  41. except ValueError as e:
  42. expected_exceptions = [
  43. "subsection not found",
  44. "Unable to handle non-minute offset",
  45. ]
  46. if is_expected_exception(expected_exceptions, e):
  47. return -1
  48. else:
  49. raise e
  50. commit2 = Commit()
  51. commit2.tree = tree.id
  52. commit2.parents = [commit.id]
  53. commit2.author = commit.author
  54. commit2.committer = commit.committer
  55. commit2.commit_time = fdp.ConsumeRandomInt()
  56. commit2.commit_timezone = fdp.ConsumeRandomInt()
  57. commit2.author_time = fdp.ConsumeRandomInt()
  58. commit2.author_timezone = fdp.ConsumeRandomInt()
  59. commit2.message = fdp.ConsumeRandomBytes()
  60. try:
  61. blob.data = fdp.ConsumeRandomBytes()
  62. repo.object_store.add_object(blob)
  63. repo.object_store.add_object(tree)
  64. repo.object_store.add_object(commit2)
  65. out = BytesIO()
  66. write_tree_diff(out, repo.object_store, commit.tree, tree.id)
  67. except (InvalidUserIdentity, ObjectFormatException):
  68. return -1
  69. except ValueError as e:
  70. expected_exceptions = [
  71. "Unable to handle non-minute offset",
  72. ]
  73. if is_expected_exception(expected_exceptions, e):
  74. return -1
  75. else:
  76. raise e
  77. def main():
  78. atheris.Setup(sys.argv, TestOneInput)
  79. atheris.Fuzz()
  80. if __name__ == "__main__":
  81. main()