2
0

fuzz_object_store.py 2.9 KB

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