fuzz_object_store.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import sys
  2. import stat
  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.objects import Blob, Tree, Commit, S_IFGITLINK
  9. from dulwich.errors import ObjectFormatException
  10. from dulwich.patch import write_tree_diff
  11. from dulwich.repo import (
  12. MemoryRepo,
  13. InvalidUserIdentity,
  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()