rugged 0.26.7 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/rugged/rugged_blame.c +6 -3
  4. data/ext/rugged/rugged_branch_collection.c +3 -6
  5. data/ext/rugged/rugged_commit.c +56 -0
  6. data/ext/rugged/rugged_config.c +44 -9
  7. data/ext/rugged/rugged_diff.c +3 -14
  8. data/ext/rugged/rugged_diff_hunk.c +1 -3
  9. data/ext/rugged/rugged_index.c +1 -5
  10. data/ext/rugged/rugged_note.c +1 -4
  11. data/ext/rugged/rugged_patch.c +1 -4
  12. data/ext/rugged/rugged_reference_collection.c +1 -7
  13. data/ext/rugged/rugged_remote.c +5 -8
  14. data/ext/rugged/rugged_remote_collection.c +1 -6
  15. data/ext/rugged/rugged_repo.c +16 -48
  16. data/ext/rugged/rugged_revwalk.c +7 -16
  17. data/ext/rugged/rugged_settings.c +28 -0
  18. data/ext/rugged/rugged_submodule_collection.c +3 -4
  19. data/ext/rugged/rugged_tag_collection.c +1 -5
  20. data/ext/rugged/rugged_tree.c +2 -3
  21. data/lib/rugged/repository.rb +43 -0
  22. data/lib/rugged/version.rb +1 -1
  23. data/vendor/libgit2/AUTHORS +1 -0
  24. data/vendor/libgit2/CMakeLists.txt +61 -510
  25. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +14 -0
  26. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +25 -8
  27. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +27 -8
  28. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +20 -0
  29. data/vendor/libgit2/cmake/Modules/IdeSplitSources.cmake +22 -0
  30. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +3 -0
  31. data/vendor/libgit2/deps/regex/CMakeLists.txt +2 -0
  32. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +26 -0
  33. data/vendor/libgit2/deps/zlib/CMakeLists.txt +4 -0
  34. data/vendor/libgit2/include/git2/config.h +29 -2
  35. data/vendor/libgit2/include/git2/describe.h +1 -1
  36. data/vendor/libgit2/include/git2/diff.h +59 -8
  37. data/vendor/libgit2/include/git2/graph.h +3 -0
  38. data/vendor/libgit2/include/git2/merge.h +6 -0
  39. data/vendor/libgit2/include/git2/message.h +43 -3
  40. data/vendor/libgit2/include/git2/notes.h +89 -0
  41. data/vendor/libgit2/include/git2/odb.h +8 -1
  42. data/vendor/libgit2/include/git2/patch.h +2 -2
  43. data/vendor/libgit2/include/git2/pathspec.h +35 -18
  44. data/vendor/libgit2/include/git2/refs.h +3 -0
  45. data/vendor/libgit2/include/git2/remote.h +34 -4
  46. data/vendor/libgit2/include/git2/repository.h +6 -6
  47. data/vendor/libgit2/include/git2/reset.h +4 -4
  48. data/vendor/libgit2/include/git2/status.h +4 -0
  49. data/vendor/libgit2/include/git2/sys/config.h +4 -1
  50. data/vendor/libgit2/include/git2/sys/odb_backend.h +2 -1
  51. data/vendor/libgit2/include/git2/tree.h +4 -3
  52. data/vendor/libgit2/include/git2/types.h +1 -0
  53. data/vendor/libgit2/include/git2/version.h +4 -4
  54. data/vendor/libgit2/include/git2/worktree.h +1 -1
  55. data/vendor/libgit2/src/CMakeLists.txt +463 -0
  56. data/vendor/libgit2/src/annotated_commit.c +1 -1
  57. data/vendor/libgit2/src/annotated_commit.h +2 -0
  58. data/vendor/libgit2/src/apply.c +2 -1
  59. data/vendor/libgit2/src/apply.h +2 -0
  60. data/vendor/libgit2/src/attr.c +24 -4
  61. data/vendor/libgit2/src/attr.h +2 -0
  62. data/vendor/libgit2/src/attr_file.c +9 -2
  63. data/vendor/libgit2/src/attr_file.h +2 -0
  64. data/vendor/libgit2/src/attrcache.c +9 -1
  65. data/vendor/libgit2/src/attrcache.h +2 -0
  66. data/vendor/libgit2/src/blame.c +1 -0
  67. data/vendor/libgit2/src/blame.h +2 -1
  68. data/vendor/libgit2/src/blame_git.c +1 -0
  69. data/vendor/libgit2/src/blame_git.h +2 -0
  70. data/vendor/libgit2/src/blob.c +2 -2
  71. data/vendor/libgit2/src/blob.h +2 -0
  72. data/vendor/libgit2/src/branch.c +8 -1
  73. data/vendor/libgit2/src/branch.h +2 -0
  74. data/vendor/libgit2/src/buf_text.c +7 -7
  75. data/vendor/libgit2/src/buf_text.h +3 -3
  76. data/vendor/libgit2/src/buffer.c +31 -1
  77. data/vendor/libgit2/src/buffer.h +3 -0
  78. data/vendor/libgit2/src/cache.c +2 -2
  79. data/vendor/libgit2/src/cache.h +2 -0
  80. data/vendor/libgit2/src/cc-compat.h +3 -3
  81. data/vendor/libgit2/src/checkout.c +30 -19
  82. data/vendor/libgit2/src/checkout.h +2 -0
  83. data/vendor/libgit2/src/cherrypick.c +1 -0
  84. data/vendor/libgit2/src/clone.c +2 -1
  85. data/vendor/libgit2/src/clone.h +4 -0
  86. data/vendor/libgit2/src/commit.c +2 -1
  87. data/vendor/libgit2/src/commit.h +2 -0
  88. data/vendor/libgit2/src/commit_list.c +1 -1
  89. data/vendor/libgit2/src/commit_list.h +2 -0
  90. data/vendor/libgit2/src/common.h +11 -5
  91. data/vendor/libgit2/src/config.c +12 -10
  92. data/vendor/libgit2/src/config.h +2 -0
  93. data/vendor/libgit2/src/config_cache.c +1 -0
  94. data/vendor/libgit2/src/config_file.c +287 -786
  95. data/vendor/libgit2/src/config_file.h +4 -3
  96. data/vendor/libgit2/src/config_parse.c +525 -0
  97. data/vendor/libgit2/src/config_parse.h +64 -0
  98. data/vendor/libgit2/src/crlf.c +2 -1
  99. data/vendor/libgit2/src/delta.c +28 -30
  100. data/vendor/libgit2/src/delta.h +1 -0
  101. data/vendor/libgit2/src/describe.c +3 -1
  102. data/vendor/libgit2/src/diff.c +148 -2
  103. data/vendor/libgit2/src/diff.h +3 -1
  104. data/vendor/libgit2/src/diff_driver.c +12 -9
  105. data/vendor/libgit2/src/diff_driver.h +4 -1
  106. data/vendor/libgit2/src/diff_file.c +7 -4
  107. data/vendor/libgit2/src/diff_file.h +1 -0
  108. data/vendor/libgit2/src/diff_generate.c +6 -3
  109. data/vendor/libgit2/src/diff_generate.h +6 -1
  110. data/vendor/libgit2/src/diff_parse.c +5 -4
  111. data/vendor/libgit2/src/diff_parse.h +2 -0
  112. data/vendor/libgit2/src/diff_print.c +2 -0
  113. data/vendor/libgit2/src/diff_stats.c +2 -0
  114. data/vendor/libgit2/src/diff_tform.c +2 -1
  115. data/vendor/libgit2/src/diff_tform.h +4 -1
  116. data/vendor/libgit2/src/diff_xdiff.c +5 -2
  117. data/vendor/libgit2/src/diff_xdiff.h +2 -0
  118. data/vendor/libgit2/src/errors.c +2 -0
  119. data/vendor/libgit2/src/features.h.in +36 -0
  120. data/vendor/libgit2/src/fetch.c +2 -2
  121. data/vendor/libgit2/src/fetch.h +4 -0
  122. data/vendor/libgit2/src/fetchhead.c +3 -3
  123. data/vendor/libgit2/src/fetchhead.h +3 -0
  124. data/vendor/libgit2/src/filebuf.c +2 -1
  125. data/vendor/libgit2/src/filebuf.h +2 -0
  126. data/vendor/libgit2/src/fileops.c +12 -1
  127. data/vendor/libgit2/src/fileops.h +7 -1
  128. data/vendor/libgit2/src/filter.c +2 -1
  129. data/vendor/libgit2/src/filter.h +1 -0
  130. data/vendor/libgit2/src/fnmatch.c +2 -2
  131. data/vendor/libgit2/src/fnmatch.h +3 -4
  132. data/vendor/libgit2/src/global.c +4 -3
  133. data/vendor/libgit2/src/global.h +1 -5
  134. data/vendor/libgit2/src/graph.c +2 -0
  135. data/vendor/libgit2/src/hash.c +0 -1
  136. data/vendor/libgit2/src/hash.h +3 -1
  137. data/vendor/libgit2/src/hash/hash_collisiondetect.h +3 -3
  138. data/vendor/libgit2/src/hash/hash_common_crypto.h +18 -5
  139. data/vendor/libgit2/src/hash/hash_generic.c +2 -2
  140. data/vendor/libgit2/src/hash/hash_generic.h +5 -3
  141. data/vendor/libgit2/src/hash/hash_openssl.h +3 -3
  142. data/vendor/libgit2/src/hash/hash_win32.c +57 -14
  143. data/vendor/libgit2/src/hash/hash_win32.h +4 -3
  144. data/vendor/libgit2/src/hashsig.c +3 -0
  145. data/vendor/libgit2/src/ident.c +2 -0
  146. data/vendor/libgit2/src/idxmap.h +2 -1
  147. data/vendor/libgit2/src/ignore.c +14 -2
  148. data/vendor/libgit2/src/ignore.h +2 -0
  149. data/vendor/libgit2/src/index.c +20 -40
  150. data/vendor/libgit2/src/index.h +2 -0
  151. data/vendor/libgit2/src/indexer.c +13 -5
  152. data/vendor/libgit2/src/indexer.h +5 -1
  153. data/vendor/libgit2/src/integer.h +1 -1
  154. data/vendor/libgit2/src/iterator.c +44 -3
  155. data/vendor/libgit2/src/iterator.h +3 -0
  156. data/vendor/libgit2/src/map.h +1 -1
  157. data/vendor/libgit2/src/merge.c +155 -33
  158. data/vendor/libgit2/src/merge.h +2 -0
  159. data/vendor/libgit2/src/merge_driver.c +2 -2
  160. data/vendor/libgit2/src/merge_driver.h +2 -0
  161. data/vendor/libgit2/src/merge_file.c +3 -0
  162. data/vendor/libgit2/src/message.h +3 -1
  163. data/vendor/libgit2/src/mwindow.c +1 -1
  164. data/vendor/libgit2/src/mwindow.h +2 -0
  165. data/vendor/libgit2/src/netops.c +75 -62
  166. data/vendor/libgit2/src/netops.h +2 -1
  167. data/vendor/libgit2/src/notes.c +164 -48
  168. data/vendor/libgit2/src/notes.h +1 -1
  169. data/vendor/libgit2/src/object.c +14 -3
  170. data/vendor/libgit2/src/object.h +4 -0
  171. data/vendor/libgit2/src/object_api.c +3 -2
  172. data/vendor/libgit2/src/odb.c +104 -38
  173. data/vendor/libgit2/src/odb.h +3 -1
  174. data/vendor/libgit2/src/odb_loose.c +414 -267
  175. data/vendor/libgit2/src/odb_mempack.c +1 -0
  176. data/vendor/libgit2/src/odb_pack.c +2 -1
  177. data/vendor/libgit2/src/offmap.h +1 -0
  178. data/vendor/libgit2/src/oid.c +2 -1
  179. data/vendor/libgit2/src/oid.h +3 -8
  180. data/vendor/libgit2/src/oidarray.c +2 -1
  181. data/vendor/libgit2/src/oidarray.h +1 -0
  182. data/vendor/libgit2/src/oidmap.h +1 -0
  183. data/vendor/libgit2/src/pack-objects.c +5 -1
  184. data/vendor/libgit2/src/pack-objects.h +1 -1
  185. data/vendor/libgit2/src/pack.c +2 -6
  186. data/vendor/libgit2/src/pack.h +2 -1
  187. data/vendor/libgit2/src/parse.c +121 -0
  188. data/vendor/libgit2/src/parse.h +61 -0
  189. data/vendor/libgit2/src/patch.c +9 -2
  190. data/vendor/libgit2/src/patch.h +2 -0
  191. data/vendor/libgit2/src/patch_generate.c +6 -5
  192. data/vendor/libgit2/src/patch_generate.h +1 -0
  193. data/vendor/libgit2/src/patch_parse.c +265 -276
  194. data/vendor/libgit2/src/patch_parse.h +6 -11
  195. data/vendor/libgit2/src/path.c +24 -181
  196. data/vendor/libgit2/src/path.h +14 -73
  197. data/vendor/libgit2/src/pathspec.c +2 -1
  198. data/vendor/libgit2/src/pathspec.h +2 -1
  199. data/vendor/libgit2/src/pool.c +8 -0
  200. data/vendor/libgit2/src/pool.h +1 -0
  201. data/vendor/libgit2/src/posix.c +2 -1
  202. data/vendor/libgit2/src/posix.h +1 -0
  203. data/vendor/libgit2/src/pqueue.c +1 -0
  204. data/vendor/libgit2/src/pqueue.h +2 -0
  205. data/vendor/libgit2/src/proxy.c +2 -1
  206. data/vendor/libgit2/src/proxy.h +3 -1
  207. data/vendor/libgit2/src/push.c +4 -171
  208. data/vendor/libgit2/src/push.h +2 -0
  209. data/vendor/libgit2/src/rebase.c +1 -0
  210. data/vendor/libgit2/src/refdb.c +2 -3
  211. data/vendor/libgit2/src/refdb.h +2 -0
  212. data/vendor/libgit2/src/refdb_fs.c +5 -3
  213. data/vendor/libgit2/src/refdb_fs.h +4 -0
  214. data/vendor/libgit2/src/reflog.c +1 -0
  215. data/vendor/libgit2/src/reflog.h +2 -1
  216. data/vendor/libgit2/src/refs.c +1 -0
  217. data/vendor/libgit2/src/refs.h +2 -1
  218. data/vendor/libgit2/src/refspec.c +2 -2
  219. data/vendor/libgit2/src/refspec.h +2 -0
  220. data/vendor/libgit2/src/remote.c +56 -10
  221. data/vendor/libgit2/src/remote.h +2 -0
  222. data/vendor/libgit2/src/repository.c +16 -14
  223. data/vendor/libgit2/src/repository.h +2 -0
  224. data/vendor/libgit2/src/reset.c +6 -5
  225. data/vendor/libgit2/src/revert.c +1 -0
  226. data/vendor/libgit2/src/revparse.c +3 -5
  227. data/vendor/libgit2/src/revwalk.c +2 -2
  228. data/vendor/libgit2/src/revwalk.h +2 -0
  229. data/vendor/libgit2/src/settings.c +6 -8
  230. data/vendor/libgit2/src/sha1_lookup.c +2 -216
  231. data/vendor/libgit2/src/sha1_lookup.h +2 -6
  232. data/vendor/libgit2/src/signature.c +8 -3
  233. data/vendor/libgit2/src/signature.h +2 -0
  234. data/vendor/libgit2/src/sortedcache.c +7 -0
  235. data/vendor/libgit2/src/sortedcache.h +2 -0
  236. data/vendor/libgit2/src/stash.c +1 -0
  237. data/vendor/libgit2/src/status.c +14 -9
  238. data/vendor/libgit2/src/status.h +2 -0
  239. data/vendor/libgit2/src/{curl_stream.c → streams/curl.c} +2 -0
  240. data/vendor/libgit2/src/{curl_stream.h → streams/curl.h} +4 -2
  241. data/vendor/libgit2/src/{openssl_stream.c → streams/openssl.c} +47 -18
  242. data/vendor/libgit2/src/{openssl_stream.h → streams/openssl.h} +6 -2
  243. data/vendor/libgit2/src/{socket_stream.c → streams/socket.c} +2 -2
  244. data/vendor/libgit2/src/{socket_stream.h → streams/socket.h} +4 -2
  245. data/vendor/libgit2/src/{stransport_stream.c → streams/stransport.c} +4 -2
  246. data/vendor/libgit2/src/{stransport_stream.h → streams/stransport.h} +4 -2
  247. data/vendor/libgit2/src/{tls_stream.c → streams/tls.c} +4 -3
  248. data/vendor/libgit2/src/{tls_stream.h → streams/tls.h} +4 -2
  249. data/vendor/libgit2/src/submodule.c +28 -80
  250. data/vendor/libgit2/src/submodule.h +2 -13
  251. data/vendor/libgit2/src/sysdir.c +75 -8
  252. data/vendor/libgit2/src/sysdir.h +2 -1
  253. data/vendor/libgit2/src/tag.c +2 -2
  254. data/vendor/libgit2/src/tag.h +2 -0
  255. data/vendor/libgit2/src/thread-utils.c +1 -0
  256. data/vendor/libgit2/src/thread-utils.h +1 -1
  257. data/vendor/libgit2/src/trace.c +2 -2
  258. data/vendor/libgit2/src/trace.h +2 -0
  259. data/vendor/libgit2/src/trailer.c +416 -0
  260. data/vendor/libgit2/src/transaction.c +2 -1
  261. data/vendor/libgit2/src/transport.c +2 -0
  262. data/vendor/libgit2/src/transports/auth.c +2 -1
  263. data/vendor/libgit2/src/transports/auth.h +4 -3
  264. data/vendor/libgit2/src/transports/auth_negotiate.c +2 -1
  265. data/vendor/libgit2/src/transports/auth_negotiate.h +3 -3
  266. data/vendor/libgit2/src/transports/cred.c +2 -0
  267. data/vendor/libgit2/src/transports/cred.h +4 -2
  268. data/vendor/libgit2/src/transports/cred_helpers.c +1 -0
  269. data/vendor/libgit2/src/transports/git.c +3 -1
  270. data/vendor/libgit2/src/transports/http.c +10 -14
  271. data/vendor/libgit2/src/transports/http.h +23 -0
  272. data/vendor/libgit2/src/transports/local.c +23 -5
  273. data/vendor/libgit2/src/transports/smart.c +3 -1
  274. data/vendor/libgit2/src/transports/smart.h +23 -16
  275. data/vendor/libgit2/src/transports/smart_pkt.c +114 -130
  276. data/vendor/libgit2/src/transports/smart_protocol.c +26 -22
  277. data/vendor/libgit2/src/transports/ssh.c +12 -7
  278. data/vendor/libgit2/src/transports/ssh.h +4 -2
  279. data/vendor/libgit2/src/transports/winhttp.c +19 -21
  280. data/vendor/libgit2/src/tree-cache.c +1 -0
  281. data/vendor/libgit2/src/tree-cache.h +1 -0
  282. data/vendor/libgit2/src/tree.c +20 -14
  283. data/vendor/libgit2/src/tree.h +2 -0
  284. data/vendor/libgit2/src/tsort.c +0 -1
  285. data/vendor/libgit2/src/unix/map.c +4 -1
  286. data/vendor/libgit2/src/unix/posix.h +8 -4
  287. data/vendor/libgit2/src/unix/pthread.h +1 -1
  288. data/vendor/libgit2/src/unix/realpath.c +4 -1
  289. data/vendor/libgit2/src/util.c +6 -5
  290. data/vendor/libgit2/src/util.h +39 -111
  291. data/vendor/libgit2/src/varint.c +0 -1
  292. data/vendor/libgit2/src/varint.h +2 -0
  293. data/vendor/libgit2/src/vector.c +1 -1
  294. data/vendor/libgit2/src/win32/dir.c +3 -0
  295. data/vendor/libgit2/src/win32/dir.h +4 -3
  296. data/vendor/libgit2/src/win32/error.c +1 -1
  297. data/vendor/libgit2/src/win32/error.h +4 -2
  298. data/vendor/libgit2/src/win32/findfile.c +2 -1
  299. data/vendor/libgit2/src/win32/findfile.h +4 -2
  300. data/vendor/libgit2/src/win32/map.c +2 -0
  301. data/vendor/libgit2/src/win32/mingw-compat.h +3 -3
  302. data/vendor/libgit2/src/win32/msvc-compat.h +3 -3
  303. data/vendor/libgit2/src/win32/path_w32.c +7 -12
  304. data/vendor/libgit2/src/win32/path_w32.h +3 -2
  305. data/vendor/libgit2/src/win32/posix.h +2 -2
  306. data/vendor/libgit2/src/win32/posix_w32.c +11 -5
  307. data/vendor/libgit2/src/win32/precompiled.h +2 -1
  308. data/vendor/libgit2/src/win32/reparse.h +2 -2
  309. data/vendor/libgit2/src/win32/thread.c +1 -0
  310. data/vendor/libgit2/src/win32/thread.h +2 -2
  311. data/vendor/libgit2/src/win32/utf-conv.c +0 -1
  312. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  313. data/vendor/libgit2/src/win32/w32_buffer.c +1 -1
  314. data/vendor/libgit2/src/win32/w32_buffer.h +4 -2
  315. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +2 -1
  316. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +85 -2
  317. data/vendor/libgit2/src/win32/w32_stack.c +2 -1
  318. data/vendor/libgit2/src/win32/w32_stack.h +5 -3
  319. data/vendor/libgit2/src/win32/w32_util.h +4 -2
  320. data/vendor/libgit2/src/win32/win32-compat.h +3 -3
  321. data/vendor/libgit2/src/worktree.c +4 -5
  322. data/vendor/libgit2/src/worktree.h +2 -0
  323. data/vendor/libgit2/src/xdiff/xdiff.h +22 -13
  324. data/vendor/libgit2/src/xdiff/xdiffi.c +523 -81
  325. data/vendor/libgit2/src/xdiff/xdiffi.h +2 -2
  326. data/vendor/libgit2/src/xdiff/xemit.c +63 -39
  327. data/vendor/libgit2/src/xdiff/xemit.h +2 -2
  328. data/vendor/libgit2/src/xdiff/xhistogram.c +0 -1
  329. data/vendor/libgit2/src/xdiff/xinclude.h +3 -2
  330. data/vendor/libgit2/src/xdiff/xmacros.h +2 -2
  331. data/vendor/libgit2/src/xdiff/xmerge.c +80 -20
  332. data/vendor/libgit2/src/xdiff/xpatience.c +41 -9
  333. data/vendor/libgit2/src/xdiff/xprepare.c +2 -2
  334. data/vendor/libgit2/src/xdiff/xprepare.h +2 -2
  335. data/vendor/libgit2/src/xdiff/xtypes.h +2 -2
  336. data/vendor/libgit2/src/xdiff/xutils.c +47 -27
  337. data/vendor/libgit2/src/xdiff/xutils.h +2 -5
  338. data/vendor/libgit2/src/zstream.c +65 -45
  339. data/vendor/libgit2/src/zstream.h +9 -2
  340. metadata +27 -13
  341. data/vendor/libgit2/include/git2/sys/remote.h +0 -16
@@ -29,4 +29,4 @@ struct git_note {
29
29
  char *message;
30
30
  };
31
31
 
32
- #endif /* INCLUDE_notes_h__ */
32
+ #endif
@@ -4,9 +4,11 @@
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
+
8
+ #include "object.h"
9
+
7
10
  #include "git2/object.h"
8
11
 
9
- #include "common.h"
10
12
  #include "repository.h"
11
13
 
12
14
  #include "commit.h"
@@ -233,14 +235,23 @@ const char *git_object_type2string(git_otype type)
233
235
  }
234
236
 
235
237
  git_otype git_object_string2type(const char *str)
238
+ {
239
+ if (!str)
240
+ return GIT_OBJ_BAD;
241
+
242
+ return git_object_stringn2type(str, strlen(str));
243
+ }
244
+
245
+ git_otype git_object_stringn2type(const char *str, size_t len)
236
246
  {
237
247
  size_t i;
238
248
 
239
- if (!str || !*str)
249
+ if (!str || !len || !*str)
240
250
  return GIT_OBJ_BAD;
241
251
 
242
252
  for (i = 0; i < ARRAY_SIZE(git_objects_table); i++)
243
- if (!strcmp(str, git_objects_table[i].str))
253
+ if (*git_objects_table[i].str &&
254
+ !git__prefixncmp(str, len, git_objects_table[i].str))
244
255
  return (git_otype)i;
245
256
 
246
257
  return GIT_OBJ_BAD;
@@ -7,6 +7,8 @@
7
7
  #ifndef INCLUDE_object_h__
8
8
  #define INCLUDE_object_h__
9
9
 
10
+ #include "common.h"
11
+
10
12
  #include "repository.h"
11
13
 
12
14
  extern bool git_object__strict_input_validation;
@@ -28,6 +30,8 @@ int git_object__from_odb_object(
28
30
 
29
31
  int git_object__resolve_to_type(git_object **obj, git_otype type);
30
32
 
33
+ git_otype git_object_stringn2type(const char *str, size_t len);
34
+
31
35
  int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
32
36
 
33
37
  void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
@@ -4,11 +4,12 @@
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
- #include "git2/object.h"
8
7
 
9
8
  #include "common.h"
10
- #include "repository.h"
11
9
 
10
+ #include "git2/object.h"
11
+
12
+ #include "repository.h"
12
13
  #include "commit.h"
13
14
  #include "tree.h"
14
15
  #include "blob.h"
@@ -5,13 +5,13 @@
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
 
8
- #include "common.h"
8
+ #include "odb.h"
9
+
9
10
  #include <zlib.h>
10
11
  #include "git2/object.h"
11
12
  #include "git2/sys/odb_backend.h"
12
13
  #include "fileops.h"
13
14
  #include "hash.h"
14
- #include "odb.h"
15
15
  #include "delta.h"
16
16
  #include "filter.h"
17
17
  #include "repository.h"
@@ -53,6 +53,7 @@ static git_cache *odb_cache(git_odb *odb)
53
53
 
54
54
  static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id);
55
55
  static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
56
+ static int error_null_oid(int error, const char *message);
56
57
 
57
58
  static git_otype odb_hardcoded_type(const git_oid *id)
58
59
  {
@@ -65,50 +66,75 @@ static git_otype odb_hardcoded_type(const git_oid *id)
65
66
  return GIT_OBJ_BAD;
66
67
  }
67
68
 
68
- static int odb_read_hardcoded(git_rawobj *raw, const git_oid *id)
69
+ static int odb_read_hardcoded(bool *found, git_rawobj *raw, const git_oid *id)
69
70
  {
70
- git_otype type = odb_hardcoded_type(id);
71
- if (type == GIT_OBJ_BAD)
72
- return -1;
71
+ git_otype type;
72
+
73
+ *found = false;
74
+
75
+ if ((type = odb_hardcoded_type(id)) == GIT_OBJ_BAD)
76
+ return 0;
73
77
 
74
78
  raw->type = type;
75
79
  raw->len = 0;
76
80
  raw->data = git__calloc(1, sizeof(uint8_t));
81
+ GITERR_CHECK_ALLOC(raw->data);
82
+
83
+ *found = true;
77
84
  return 0;
78
85
  }
79
86
 
80
- int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type)
87
+ int git_odb__format_object_header(
88
+ size_t *written,
89
+ char *hdr,
90
+ size_t hdr_size,
91
+ git_off_t obj_len,
92
+ git_otype obj_type)
81
93
  {
82
94
  const char *type_str = git_object_type2string(obj_type);
83
- int len = p_snprintf(hdr, n, "%s %lld", type_str, (long long)obj_len);
84
- assert(len > 0 && len <= (int)n);
85
- return len+1;
95
+ int hdr_max = (hdr_size > INT_MAX-2) ? (INT_MAX-2) : (int)hdr_size;
96
+ int len;
97
+
98
+ len = p_snprintf(hdr, hdr_max, "%s %lld", type_str, (long long)obj_len);
99
+
100
+ if (len < 0 || len >= hdr_max) {
101
+ giterr_set(GITERR_OS, "object header creation failed");
102
+ return -1;
103
+ }
104
+
105
+ *written = (size_t)(len + 1);
106
+ return 0;
86
107
  }
87
108
 
88
109
  int git_odb__hashobj(git_oid *id, git_rawobj *obj)
89
110
  {
90
111
  git_buf_vec vec[2];
91
112
  char header[64];
92
- int hdrlen;
113
+ size_t hdrlen;
114
+ int error;
93
115
 
94
116
  assert(id && obj);
95
117
 
96
- if (!git_object_typeisloose(obj->type))
118
+ if (!git_object_typeisloose(obj->type)) {
119
+ giterr_set(GITERR_INVALID, "invalid object type");
97
120
  return -1;
121
+ }
98
122
 
99
- if (!obj->data && obj->len != 0)
123
+ if (!obj->data && obj->len != 0) {
124
+ giterr_set(GITERR_INVALID, "invalid object");
100
125
  return -1;
126
+ }
101
127
 
102
- hdrlen = git_odb__format_object_header(header, sizeof(header), obj->len, obj->type);
128
+ if ((error = git_odb__format_object_header(&hdrlen,
129
+ header, sizeof(header), obj->len, obj->type)) < 0)
130
+ return error;
103
131
 
104
132
  vec[0].data = header;
105
133
  vec[0].len = hdrlen;
106
134
  vec[1].data = obj->data;
107
135
  vec[1].len = obj->len;
108
136
 
109
- git_hash_vec(id, vec, 2);
110
-
111
- return 0;
137
+ return git_hash_vec(id, vec, 2);
112
138
  }
113
139
 
114
140
 
@@ -171,7 +197,7 @@ void git_odb_object_free(git_odb_object *object)
171
197
 
172
198
  int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
173
199
  {
174
- int hdr_len;
200
+ size_t hdr_len;
175
201
  char hdr[64], buffer[FILEIO_BUFSIZE];
176
202
  git_hash_ctx ctx;
177
203
  ssize_t read_len = 0;
@@ -183,9 +209,11 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
183
209
  }
184
210
 
185
211
  if ((error = git_hash_ctx_init(&ctx)) < 0)
186
- return -1;
212
+ return error;
187
213
 
188
- hdr_len = git_odb__format_object_header(hdr, sizeof(hdr), size, type);
214
+ if ((error = git_odb__format_object_header(&hdr_len, hdr,
215
+ sizeof(hdr), size, type)) < 0)
216
+ goto done;
189
217
 
190
218
  if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0)
191
219
  goto done;
@@ -341,8 +369,7 @@ static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t
341
369
  {
342
370
  fake_wstream *stream = (fake_wstream *)_stream;
343
371
 
344
- if (stream->written + len > stream->size)
345
- return -1;
372
+ assert(stream->written + len <= stream->size);
346
373
 
347
374
  memcpy(stream->buffer + stream->written, data, len);
348
375
  stream->written += len;
@@ -735,6 +762,9 @@ int git_odb_exists(git_odb *db, const git_oid *id)
735
762
 
736
763
  assert(db && id);
737
764
 
765
+ if (git_oid_iszero(id))
766
+ return 0;
767
+
738
768
  if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
739
769
  git_odb_object_free(object);
740
770
  return 1;
@@ -796,7 +826,7 @@ int git_odb_exists_prefix(
796
826
  git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
797
827
  {
798
828
  int error;
799
- git_oid key = {{0}};
829
+ git_oid key = {{0}};
800
830
 
801
831
  assert(db && short_id);
802
832
 
@@ -958,6 +988,11 @@ int git_odb__read_header_or_object(
958
988
 
959
989
  assert(db && id && out && len_p && type_p);
960
990
 
991
+ *out = NULL;
992
+
993
+ if (git_oid_iszero(id))
994
+ return error_null_oid(GIT_ENOTFOUND, "cannot read object");
995
+
961
996
  if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
962
997
  *len_p = object->cached.size;
963
998
  *type_p = object->cached.type;
@@ -965,7 +1000,6 @@ int git_odb__read_header_or_object(
965
1000
  return 0;
966
1001
  }
967
1002
 
968
- *out = NULL;
969
1003
  error = odb_read_header_1(len_p, type_p, db, id, false);
970
1004
 
971
1005
  if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
@@ -1004,8 +1038,10 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
1004
1038
  bool found = false;
1005
1039
  int error = 0;
1006
1040
 
1007
- if (!only_refreshed && odb_read_hardcoded(&raw, id) == 0)
1008
- found = true;
1041
+ if (!only_refreshed) {
1042
+ if ((error = odb_read_hardcoded(&found, &raw, id)) < 0)
1043
+ return error;
1044
+ }
1009
1045
 
1010
1046
  for (i = 0; i < db->backends.length && !found; ++i) {
1011
1047
  backend_internal *internal = git_vector_get(&db->backends, i);
@@ -1040,8 +1076,10 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
1040
1076
  }
1041
1077
 
1042
1078
  giterr_clear();
1043
- if ((object = odb_object__alloc(id, &raw)) == NULL)
1079
+ if ((object = odb_object__alloc(id, &raw)) == NULL) {
1080
+ error = -1;
1044
1081
  goto out;
1082
+ }
1045
1083
 
1046
1084
  *out = git_cache_store_raw(odb_cache(db), object);
1047
1085
 
@@ -1057,6 +1095,9 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
1057
1095
 
1058
1096
  assert(out && db && id);
1059
1097
 
1098
+ if (git_oid_iszero(id))
1099
+ return error_null_oid(GIT_ENOTFOUND, "cannot read object");
1100
+
1060
1101
  *out = git_cache_get_raw(odb_cache(db), id);
1061
1102
  if (*out != NULL)
1062
1103
  return 0;
@@ -1078,11 +1119,14 @@ static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id)
1078
1119
  size_t _unused;
1079
1120
  int error;
1080
1121
 
1122
+ if (git_oid_iszero(id))
1123
+ return error_null_oid(GIT_ENOTFOUND, "cannot get object type");
1124
+
1081
1125
  if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
1082
1126
  *type_p = object->cached.type;
1083
1127
  return 0;
1084
1128
  }
1085
-
1129
+
1086
1130
  error = odb_read_header_1(&_unused, type_p, db, id, false);
1087
1131
 
1088
1132
  if (error == GIT_PASSTHROUGH) {
@@ -1161,8 +1205,10 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
1161
1205
  }
1162
1206
  }
1163
1207
 
1164
- if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
1208
+ if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL) {
1209
+ error = -1;
1165
1210
  goto out;
1211
+ }
1166
1212
 
1167
1213
  *out = git_cache_store_raw(odb_cache(db), object);
1168
1214
 
@@ -1231,6 +1277,10 @@ int git_odb_write(
1231
1277
  assert(oid && db);
1232
1278
 
1233
1279
  git_odb_hash(oid, data, len, type);
1280
+
1281
+ if (git_oid_iszero(oid))
1282
+ return error_null_oid(GIT_EINVALID, "cannot write object");
1283
+
1234
1284
  if (git_odb__freshen(db, oid))
1235
1285
  return 0;
1236
1286
 
@@ -1263,13 +1313,17 @@ int git_odb_write(
1263
1313
  return error;
1264
1314
  }
1265
1315
 
1266
- static void hash_header(git_hash_ctx *ctx, git_off_t size, git_otype type)
1316
+ static int hash_header(git_hash_ctx *ctx, git_off_t size, git_otype type)
1267
1317
  {
1268
1318
  char header[64];
1269
- int hdrlen;
1319
+ size_t hdrlen;
1320
+ int error;
1270
1321
 
1271
- hdrlen = git_odb__format_object_header(header, sizeof(header), size, type);
1272
- git_hash_update(ctx, header, hdrlen);
1322
+ if ((error = git_odb__format_object_header(&hdrlen,
1323
+ header, sizeof(header), size, type)) < 0)
1324
+ return error;
1325
+
1326
+ return git_hash_update(ctx, header, hdrlen);
1273
1327
  }
1274
1328
 
1275
1329
  int git_odb_open_wstream(
@@ -1310,16 +1364,17 @@ int git_odb_open_wstream(
1310
1364
  ctx = git__malloc(sizeof(git_hash_ctx));
1311
1365
  GITERR_CHECK_ALLOC(ctx);
1312
1366
 
1313
- if ((error = git_hash_ctx_init(ctx)) < 0)
1367
+ if ((error = git_hash_ctx_init(ctx)) < 0 ||
1368
+ (error = hash_header(ctx, size, type)) < 0)
1314
1369
  goto done;
1315
1370
 
1316
- hash_header(ctx, size, type);
1317
1371
  (*stream)->hash_ctx = ctx;
1318
-
1319
1372
  (*stream)->declared_size = size;
1320
1373
  (*stream)->received_bytes = 0;
1321
1374
 
1322
1375
  done:
1376
+ if (error)
1377
+ git__free(ctx);
1323
1378
  return error;
1324
1379
  }
1325
1380
 
@@ -1378,7 +1433,12 @@ void git_odb_stream_free(git_odb_stream *stream)
1378
1433
  stream->free(stream);
1379
1434
  }
1380
1435
 
1381
- int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
1436
+ int git_odb_open_rstream(
1437
+ git_odb_stream **stream,
1438
+ size_t *len,
1439
+ git_otype *type,
1440
+ git_odb *db,
1441
+ const git_oid *oid)
1382
1442
  {
1383
1443
  size_t i, reads = 0;
1384
1444
  int error = GIT_ERROR;
@@ -1391,7 +1451,7 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi
1391
1451
 
1392
1452
  if (b->readstream != NULL) {
1393
1453
  ++reads;
1394
- error = b->readstream(stream, b, oid);
1454
+ error = b->readstream(stream, len, type, b, oid);
1395
1455
  }
1396
1456
  }
1397
1457
 
@@ -1484,6 +1544,12 @@ int git_odb__error_notfound(
1484
1544
  return GIT_ENOTFOUND;
1485
1545
  }
1486
1546
 
1547
+ static int error_null_oid(int error, const char *message)
1548
+ {
1549
+ giterr_set(GITERR_ODB, "odb: %s: null OID cannot exist", message);
1550
+ return error;
1551
+ }
1552
+
1487
1553
  int git_odb__error_ambiguous(const char *message)
1488
1554
  {
1489
1555
  giterr_set(GITERR_ODB, "ambiguous SHA1 prefix - %s", message);
@@ -7,6 +7,8 @@
7
7
  #ifndef INCLUDE_odb_h__
8
8
  #define INCLUDE_odb_h__
9
9
 
10
+ #include "common.h"
11
+
10
12
  #include "git2/odb.h"
11
13
  #include "git2/oid.h"
12
14
  #include "git2/types.h"
@@ -68,7 +70,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj);
68
70
  /*
69
71
  * Format the object header such as it would appear in the on-disk object
70
72
  */
71
- int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type);
73
+ int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, git_off_t obj_len, git_otype obj_type);
72
74
  /*
73
75
  * Hash an open file descriptor.
74
76
  * This is a performance call when the contents of a fd need to be hashed,
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  #include "common.h"
9
+
9
10
  #include <zlib.h>
10
11
  #include "git2/object.h"
11
12
  #include "git2/sys/odb_backend.h"
@@ -15,10 +16,14 @@
15
16
  #include "delta.h"
16
17
  #include "filebuf.h"
17
18
  #include "object.h"
19
+ #include "zstream.h"
18
20
 
19
21
  #include "git2/odb_backend.h"
20
22
  #include "git2/types.h"
21
23
 
24
+ /* maximum possible header length */
25
+ #define MAX_HEADER_LEN 64
26
+
22
27
  typedef struct { /* object header data */
23
28
  git_otype type; /* object type */
24
29
  size_t size; /* object size */
@@ -29,6 +34,15 @@ typedef struct {
29
34
  git_filebuf fbuf;
30
35
  } loose_writestream;
31
36
 
37
+ typedef struct {
38
+ git_odb_stream stream;
39
+ git_map map;
40
+ char start[MAX_HEADER_LEN];
41
+ size_t start_len;
42
+ size_t start_read;
43
+ git_zstream zstream;
44
+ } loose_readstream;
45
+
32
46
  typedef struct loose_backend {
33
47
  git_odb_backend parent;
34
48
 
@@ -90,222 +104,117 @@ static int object_mkdir(const git_buf *name, const loose_backend *be)
90
104
  GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR, NULL);
91
105
  }
92
106
 
93
- static size_t get_binary_object_header(obj_hdr *hdr, git_buf *obj)
107
+ static int parse_header_packlike(
108
+ obj_hdr *out, size_t *out_len, const unsigned char *data, size_t len)
94
109
  {
95
110
  unsigned long c;
96
- unsigned char *data = (unsigned char *)obj->ptr;
97
111
  size_t shift, size, used = 0;
98
112
 
99
- if (git_buf_len(obj) == 0)
100
- return 0;
113
+ if (len == 0)
114
+ goto on_error;
101
115
 
102
116
  c = data[used++];
103
- hdr->type = (c >> 4) & 7;
117
+ out->type = (c >> 4) & 7;
104
118
 
105
119
  size = c & 15;
106
120
  shift = 4;
107
121
  while (c & 0x80) {
108
- if (git_buf_len(obj) <= used)
109
- return 0;
122
+ if (len <= used)
123
+ goto on_error;
124
+
110
125
  if (sizeof(size_t) * 8 <= shift)
111
- return 0;
126
+ goto on_error;
127
+
112
128
  c = data[used++];
113
129
  size += (c & 0x7f) << shift;
114
130
  shift += 7;
115
131
  }
116
- hdr->size = size;
117
-
118
- return used;
119
- }
120
-
121
- static size_t get_object_header(obj_hdr *hdr, unsigned char *data)
122
- {
123
- char c, typename[10];
124
- size_t size, used = 0;
125
-
126
- /*
127
- * type name string followed by space.
128
- */
129
- while ((c = data[used]) != ' ') {
130
- typename[used++] = c;
131
- if (used >= sizeof(typename))
132
- return 0;
133
- }
134
- typename[used] = 0;
135
- if (used == 0)
136
- return 0;
137
- hdr->type = git_object_string2type(typename);
138
- used++; /* consume the space */
139
-
140
- /*
141
- * length follows immediately in decimal (without
142
- * leading zeros).
143
- */
144
- size = data[used++] - '0';
145
- if (size > 9)
146
- return 0;
147
- if (size) {
148
- while ((c = data[used]) != '\0') {
149
- size_t d = c - '0';
150
- if (d > 9)
151
- break;
152
- used++;
153
- size = size * 10 + d;
154
- }
155
- }
156
- hdr->size = size;
157
-
158
- /*
159
- * the length must be followed by a zero byte
160
- */
161
- if (data[used++] != '\0')
162
- return 0;
163
-
164
- return used;
165
- }
166
-
167
132
 
133
+ out->size = size;
168
134
 
169
- /***********************************************************
170
- *
171
- * ZLIB RELATED FUNCTIONS
172
- *
173
- ***********************************************************/
174
-
175
- static void init_stream(z_stream *s, void *out, size_t len)
176
- {
177
- memset(s, 0, sizeof(*s));
178
- s->next_out = out;
179
- s->avail_out = (uInt)len;
180
- }
135
+ if (out_len)
136
+ *out_len = used;
181
137
 
182
- static void set_stream_input(z_stream *s, void *in, size_t len)
183
- {
184
- s->next_in = in;
185
- s->avail_in = (uInt)len;
186
- }
138
+ return 0;
187
139
 
188
- static void set_stream_output(z_stream *s, void *out, size_t len)
189
- {
190
- s->next_out = out;
191
- s->avail_out = (uInt)len;
140
+ on_error:
141
+ giterr_set(GITERR_OBJECT, "failed to parse loose object: invalid header");
142
+ return -1;
192
143
  }
193
144
 
194
-
195
- static int start_inflate(z_stream *s, git_buf *obj, void *out, size_t len)
145
+ static int parse_header(
146
+ obj_hdr *out,
147
+ size_t *out_len,
148
+ const unsigned char *_data,
149
+ size_t data_len)
196
150
  {
197
- int status;
151
+ const char *data = (char *)_data;
152
+ size_t i, typename_len, size_idx, size_len;
153
+ int64_t size;
198
154
 
199
- init_stream(s, out, len);
200
- set_stream_input(s, obj->ptr, git_buf_len(obj));
155
+ *out_len = 0;
201
156
 
202
- if ((status = inflateInit(s)) < Z_OK)
203
- return status;
157
+ /* find the object type name */
158
+ for (i = 0, typename_len = 0; i < data_len; i++, typename_len++) {
159
+ if (data[i] == ' ')
160
+ break;
161
+ }
204
162
 
205
- return inflate(s, 0);
206
- }
163
+ if (typename_len == data_len)
164
+ goto on_error;
207
165
 
208
- static void abort_inflate(z_stream *s)
209
- {
210
- inflateEnd(s);
211
- }
166
+ out->type = git_object_stringn2type(data, typename_len);
212
167
 
213
- static int finish_inflate(z_stream *s)
214
- {
215
- int status = Z_OK;
168
+ size_idx = typename_len + 1;
169
+ for (i = size_idx, size_len = 0; i < data_len; i++, size_len++) {
170
+ if (data[i] == '\0')
171
+ break;
172
+ }
216
173
 
217
- while (status == Z_OK)
218
- status = inflate(s, Z_FINISH);
174
+ if (i == data_len)
175
+ goto on_error;
219
176
 
220
- inflateEnd(s);
177
+ if (git__strntol64(&size, &data[size_idx], size_len, NULL, 10) < 0 ||
178
+ size < 0)
179
+ goto on_error;
221
180
 
222
- if ((status != Z_STREAM_END) || (s->avail_in != 0)) {
223
- giterr_set(GITERR_ZLIB, "failed to finish zlib inflation; stream aborted prematurely");
181
+ if ((uint64_t)size > SIZE_MAX) {
182
+ giterr_set(GITERR_OBJECT, "object is larger than available memory");
224
183
  return -1;
225
184
  }
226
185
 
186
+ out->size = size;
187
+
188
+ if (GIT_ADD_SIZET_OVERFLOW(out_len, i, 1))
189
+ goto on_error;
190
+
227
191
  return 0;
192
+
193
+ on_error:
194
+ giterr_set(GITERR_OBJECT, "failed to parse loose object: invalid header");
195
+ return -1;
228
196
  }
229
197
 
230
- static int is_zlib_compressed_data(unsigned char *data)
198
+ static int is_zlib_compressed_data(unsigned char *data, size_t data_len)
231
199
  {
232
200
  unsigned int w;
233
201
 
202
+ if (data_len < 2)
203
+ return 0;
204
+
234
205
  w = ((unsigned int)(data[0]) << 8) + data[1];
235
206
  return (data[0] & 0x8F) == 0x08 && !(w % 31);
236
207
  }
237
208
 
238
- static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
239
- {
240
- z_stream zs;
241
- int status = Z_OK;
242
-
243
- memset(&zs, 0x0, sizeof(zs));
244
-
245
- zs.next_out = out;
246
- zs.avail_out = (uInt)outlen;
247
-
248
- zs.next_in = in;
249
- zs.avail_in = (uInt)inlen;
250
-
251
- if (inflateInit(&zs) < Z_OK) {
252
- giterr_set(GITERR_ZLIB, "failed to inflate buffer");
253
- return -1;
254
- }
255
-
256
- while (status == Z_OK)
257
- status = inflate(&zs, Z_FINISH);
258
-
259
- inflateEnd(&zs);
260
-
261
- if (status != Z_STREAM_END /* || zs.avail_in != 0 */ ||
262
- zs.total_out != outlen)
263
- {
264
- giterr_set(GITERR_ZLIB, "failed to inflate buffer; stream aborted prematurely");
265
- return -1;
266
- }
267
-
268
- return 0;
269
- }
270
-
271
- static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
272
- {
273
- unsigned char *buf, *head = hb;
274
- size_t tail, alloc_size;
275
-
276
- /*
277
- * allocate a buffer to hold the inflated data and copy the
278
- * initial sequence of inflated data from the tail of the
279
- * head buffer, if any.
280
- */
281
- if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr->size, 1) ||
282
- (buf = git__malloc(alloc_size)) == NULL) {
283
- inflateEnd(s);
284
- return NULL;
285
- }
286
- tail = s->total_out - used;
287
- if (used > 0 && tail > 0) {
288
- if (tail > hdr->size)
289
- tail = hdr->size;
290
- memcpy(buf, head + used, tail);
291
- }
292
- used = tail;
293
-
294
- /*
295
- * inflate the remainder of the object data, if any
296
- */
297
- if (hdr->size < used)
298
- inflateEnd(s);
299
- else {
300
- set_stream_output(s, buf + used, hdr->size - used);
301
- if (finish_inflate(s)) {
302
- git__free(buf);
303
- return NULL;
304
- }
305
- }
209
+ /***********************************************************
210
+ *
211
+ * ODB OBJECT READING & WRITING
212
+ *
213
+ * Backend for the public API; read headers and full objects
214
+ * from the ODB. Write raw data to the ODB.
215
+ *
216
+ ***********************************************************/
306
217
 
307
- return buf;
308
- }
309
218
 
310
219
  /*
311
220
  * At one point, there was a loose object format that was intended to
@@ -313,98 +222,122 @@ static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
313
222
  * of loose object data into packs. This format is no longer used, but
314
223
  * we must still read it.
315
224
  */
316
- static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
225
+ static int read_loose_packlike(git_rawobj *out, git_buf *obj)
317
226
  {
318
- unsigned char *in, *buf;
227
+ git_buf body = GIT_BUF_INIT;
228
+ const unsigned char *obj_data;
319
229
  obj_hdr hdr;
320
- size_t len, used, alloclen;
230
+ size_t obj_len, head_len, alloc_size;
231
+ int error;
232
+
233
+ obj_data = (unsigned char *)obj->ptr;
234
+ obj_len = obj->size;
321
235
 
322
236
  /*
323
237
  * read the object header, which is an (uncompressed)
324
238
  * binary encoding of the object type and size.
325
239
  */
326
- if ((used = get_binary_object_header(&hdr, obj)) == 0 ||
327
- !git_object_typeisloose(hdr.type)) {
240
+ if ((error = parse_header_packlike(&hdr, &head_len, obj_data, obj_len)) < 0)
241
+ goto done;
242
+
243
+ if (!git_object_typeisloose(hdr.type) || head_len > obj_len) {
328
244
  giterr_set(GITERR_ODB, "failed to inflate loose object");
329
- return -1;
245
+ error = -1;
246
+ goto done;
330
247
  }
331
248
 
249
+ obj_data += head_len;
250
+ obj_len -= head_len;
251
+
332
252
  /*
333
253
  * allocate a buffer and inflate the data into it
334
254
  */
335
- GITERR_CHECK_ALLOC_ADD(&alloclen, hdr.size, 1);
336
- buf = git__malloc(alloclen);
337
- GITERR_CHECK_ALLOC(buf);
338
-
339
- in = ((unsigned char *)obj->ptr) + used;
340
- len = obj->size - used;
341
- if (inflate_buffer(in, len, buf, hdr.size) < 0) {
342
- git__free(buf);
343
- return -1;
255
+ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
256
+ git_buf_init(&body, alloc_size) < 0) {
257
+ error = -1;
258
+ goto done;
344
259
  }
345
- buf[hdr.size] = '\0';
346
260
 
347
- out->data = buf;
261
+ if ((error = git_zstream_inflatebuf(&body, obj_data, obj_len)) < 0)
262
+ goto done;
263
+
348
264
  out->len = hdr.size;
349
265
  out->type = hdr.type;
266
+ out->data = git_buf_detach(&body);
350
267
 
351
- return 0;
268
+ done:
269
+ git_buf_free(&body);
270
+ return error;
352
271
  }
353
272
 
354
- static int inflate_disk_obj(git_rawobj *out, git_buf *obj)
273
+ static int read_loose_standard(git_rawobj *out, git_buf *obj)
355
274
  {
356
- unsigned char head[64], *buf;
357
- z_stream zs;
275
+ git_zstream zstream = GIT_ZSTREAM_INIT;
276
+ unsigned char head[MAX_HEADER_LEN], *body = NULL;
277
+ size_t decompressed, head_len, body_len, alloc_size;
358
278
  obj_hdr hdr;
359
- size_t used;
279
+ int error;
360
280
 
361
- /*
362
- * check for a pack-like loose object
363
- */
364
- if (!is_zlib_compressed_data((unsigned char *)obj->ptr))
365
- return inflate_packlike_loose_disk_obj(out, obj);
281
+ if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0 ||
282
+ (error = git_zstream_set_input(&zstream, git_buf_cstr(obj), git_buf_len(obj))) < 0)
283
+ goto done;
284
+
285
+ decompressed = sizeof(head);
366
286
 
367
287
  /*
368
- * inflate the initial part of the io buffer in order
369
- * to parse the object header (type and size).
288
+ * inflate the initial part of the compressed buffer in order to
289
+ * parse the header; read the largest header possible, then push the
290
+ * remainder into the body buffer.
370
291
  */
371
- if (start_inflate(&zs, obj, head, sizeof(head)) < Z_OK ||
372
- (used = get_object_header(&hdr, head)) == 0 ||
373
- !git_object_typeisloose(hdr.type))
374
- {
375
- abort_inflate(&zs);
292
+ if ((error = git_zstream_get_output(head, &decompressed, &zstream)) < 0 ||
293
+ (error = parse_header(&hdr, &head_len, head, decompressed)) < 0)
294
+ goto done;
295
+
296
+ if (!git_object_typeisloose(hdr.type)) {
376
297
  giterr_set(GITERR_ODB, "failed to inflate disk object");
377
- return -1;
298
+ error = -1;
299
+ goto done;
378
300
  }
379
301
 
380
302
  /*
381
303
  * allocate a buffer and inflate the object data into it
382
304
  * (including the initial sequence in the head buffer).
383
305
  */
384
- if ((buf = inflate_tail(&zs, head, used, &hdr)) == NULL)
385
- return -1;
386
- buf[hdr.size] = '\0';
306
+ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
307
+ (body = git__malloc(alloc_size)) == NULL) {
308
+ error = -1;
309
+ goto done;
310
+ }
387
311
 
388
- out->data = buf;
389
- out->len = hdr.size;
390
- out->type = hdr.type;
312
+ assert(decompressed >= head_len);
313
+ body_len = decompressed - head_len;
391
314
 
392
- return 0;
393
- }
315
+ if (body_len)
316
+ memcpy(body, head + head_len, body_len);
394
317
 
318
+ decompressed = hdr.size - body_len;
319
+ if ((error = git_zstream_get_output(body + body_len, &decompressed, &zstream)) < 0)
320
+ goto done;
395
321
 
322
+ if (!git_zstream_done(&zstream)) {
323
+ giterr_set(GITERR_ZLIB, "failed to finish zlib inflation: stream aborted prematurely");
324
+ error = -1;
325
+ goto done;
326
+ }
396
327
 
328
+ body[hdr.size] = '\0';
397
329
 
330
+ out->data = body;
331
+ out->len = hdr.size;
332
+ out->type = hdr.type;
398
333
 
334
+ done:
335
+ if (error < 0)
336
+ git__free(body);
399
337
 
400
- /***********************************************************
401
- *
402
- * ODB OBJECT READING & WRITING
403
- *
404
- * Backend for the public API; read headers and full objects
405
- * from the ODB. Write raw data to the ODB.
406
- *
407
- ***********************************************************/
338
+ git_zstream_free(&zstream);
339
+ return error;
340
+ }
408
341
 
409
342
  static int read_loose(git_rawobj *out, git_buf *loc)
410
343
  {
@@ -420,21 +353,62 @@ static int read_loose(git_rawobj *out, git_buf *loc)
420
353
  out->len = 0;
421
354
  out->type = GIT_OBJ_BAD;
422
355
 
423
- if (!(error = git_futils_readbuffer(&obj, loc->ptr)))
424
- error = inflate_disk_obj(out, &obj);
356
+ if ((error = git_futils_readbuffer(&obj, loc->ptr)) < 0)
357
+ goto done;
425
358
 
359
+ if (!is_zlib_compressed_data((unsigned char *)obj.ptr, obj.size))
360
+ error = read_loose_packlike(out, &obj);
361
+ else
362
+ error = read_loose_standard(out, &obj);
363
+
364
+ done:
426
365
  git_buf_free(&obj);
366
+ return error;
367
+ }
368
+
369
+ static int read_header_loose_packlike(
370
+ git_rawobj *out, const unsigned char *data, size_t len)
371
+ {
372
+ obj_hdr hdr;
373
+ size_t header_len;
374
+ int error;
375
+
376
+ if ((error = parse_header_packlike(&hdr, &header_len, data, len)) < 0)
377
+ return error;
378
+
379
+ out->len = hdr.size;
380
+ out->type = hdr.type;
381
+
382
+ return error;
383
+ }
384
+
385
+ static int read_header_loose_standard(
386
+ git_rawobj *out, const unsigned char *data, size_t len)
387
+ {
388
+ git_zstream zs = GIT_ZSTREAM_INIT;
389
+ obj_hdr hdr;
390
+ unsigned char inflated[MAX_HEADER_LEN];
391
+ size_t header_len, inflated_len = sizeof(inflated);
392
+ int error;
427
393
 
394
+ if ((error = git_zstream_init(&zs, GIT_ZSTREAM_INFLATE)) < 0 ||
395
+ (error = git_zstream_set_input(&zs, data, len)) < 0 ||
396
+ (error = git_zstream_get_output_chunk(inflated, &inflated_len, &zs)) < 0 ||
397
+ (error = parse_header(&hdr, &header_len, inflated, inflated_len)) < 0)
398
+ goto done;
399
+
400
+ out->len = hdr.size;
401
+ out->type = hdr.type;
402
+
403
+ done:
404
+ git_zstream_free(&zs);
428
405
  return error;
429
406
  }
430
407
 
431
408
  static int read_header_loose(git_rawobj *out, git_buf *loc)
432
409
  {
433
- int error = 0, z_return = Z_ERRNO, read_bytes;
434
- git_file fd;
435
- z_stream zs;
436
- obj_hdr header_obj;
437
- unsigned char raw_buffer[16], inflated_buffer[64];
410
+ unsigned char obj[1024];
411
+ int fd, obj_len, error;
438
412
 
439
413
  assert(out && loc);
440
414
 
@@ -443,35 +417,24 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
443
417
 
444
418
  out->data = NULL;
445
419
 
446
- if ((fd = git_futils_open_ro(loc->ptr)) < 0)
447
- return fd;
420
+ if ((error = fd = git_futils_open_ro(loc->ptr)) < 0 ||
421
+ (error = obj_len = p_read(fd, obj, sizeof(obj))) < 0)
422
+ goto done;
448
423
 
449
- init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
450
-
451
- z_return = inflateInit(&zs);
452
-
453
- while (z_return == Z_OK) {
454
- if ((read_bytes = p_read(fd, raw_buffer, sizeof(raw_buffer))) > 0) {
455
- set_stream_input(&zs, raw_buffer, read_bytes);
456
- z_return = inflate(&zs, 0);
457
- } else
458
- z_return = Z_STREAM_END;
459
- }
424
+ if (!is_zlib_compressed_data(obj, (size_t)obj_len))
425
+ error = read_header_loose_packlike(out, obj, (size_t)obj_len);
426
+ else
427
+ error = read_header_loose_standard(out, obj, (size_t)obj_len);
460
428
 
461
- if ((z_return != Z_STREAM_END && z_return != Z_BUF_ERROR)
462
- || get_object_header(&header_obj, inflated_buffer) == 0
463
- || git_object_typeisloose(header_obj.type) == 0)
464
- {
429
+ if (!error && !git_object_typeisloose(out->type)) {
465
430
  giterr_set(GITERR_ZLIB, "failed to read loose object header");
466
431
  error = -1;
467
- } else {
468
- out->len = header_obj.size;
469
- out->type = header_obj.type;
432
+ goto done;
470
433
  }
471
434
 
472
- finish_inflate(&zs);
473
- p_close(fd);
474
-
435
+ done:
436
+ if (fd >= 0)
437
+ p_close(fd);
475
438
  return error;
476
439
  }
477
440
 
@@ -812,7 +775,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
812
775
  return error;
813
776
  }
814
777
 
815
- static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid *oid)
778
+ static int loose_backend__writestream_finalize(git_odb_stream *_stream, const git_oid *oid)
816
779
  {
817
780
  loose_writestream *stream = (loose_writestream *)_stream;
818
781
  loose_backend *backend = (loose_backend *)_stream->backend;
@@ -831,13 +794,13 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid *
831
794
  return error;
832
795
  }
833
796
 
834
- static int loose_backend__stream_write(git_odb_stream *_stream, const char *data, size_t len)
797
+ static int loose_backend__writestream_write(git_odb_stream *_stream, const char *data, size_t len)
835
798
  {
836
799
  loose_writestream *stream = (loose_writestream *)_stream;
837
800
  return git_filebuf_write(&stream->fbuf, data, len);
838
801
  }
839
802
 
840
- static void loose_backend__stream_free(git_odb_stream *_stream)
803
+ static void loose_backend__writestream_free(git_odb_stream *_stream)
841
804
  {
842
805
  loose_writestream *stream = (loose_writestream *)_stream;
843
806
 
@@ -856,29 +819,32 @@ static int filebuf_flags(loose_backend *backend)
856
819
  return flags;
857
820
  }
858
821
 
859
- static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type)
822
+ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type)
860
823
  {
861
824
  loose_backend *backend;
862
825
  loose_writestream *stream = NULL;
863
- char hdr[64];
826
+ char hdr[MAX_HEADER_LEN];
864
827
  git_buf tmp_path = GIT_BUF_INIT;
865
- int hdrlen;
828
+ size_t hdrlen;
829
+ int error;
866
830
 
867
831
  assert(_backend && length >= 0);
868
832
 
869
833
  backend = (loose_backend *)_backend;
870
834
  *stream_out = NULL;
871
835
 
872
- hdrlen = git_odb__format_object_header(hdr, sizeof(hdr), length, type);
836
+ if ((error = git_odb__format_object_header(&hdrlen,
837
+ hdr, sizeof(hdr), length, type)) < 0)
838
+ return error;
873
839
 
874
840
  stream = git__calloc(1, sizeof(loose_writestream));
875
841
  GITERR_CHECK_ALLOC(stream);
876
842
 
877
843
  stream->stream.backend = _backend;
878
844
  stream->stream.read = NULL; /* read only */
879
- stream->stream.write = &loose_backend__stream_write;
880
- stream->stream.finalize_write = &loose_backend__stream_fwrite;
881
- stream->stream.free = &loose_backend__stream_free;
845
+ stream->stream.write = &loose_backend__writestream_write;
846
+ stream->stream.finalize_write = &loose_backend__writestream_finalize;
847
+ stream->stream.free = &loose_backend__writestream_free;
882
848
  stream->stream.mode = GIT_STREAM_WRONLY;
883
849
 
884
850
  if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
@@ -896,18 +862,198 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
896
862
  return !stream ? -1 : 0;
897
863
  }
898
864
 
865
+ static int loose_backend__readstream_read(
866
+ git_odb_stream *_stream,
867
+ char *buffer,
868
+ size_t buffer_len)
869
+ {
870
+ loose_readstream *stream = (loose_readstream *)_stream;
871
+ size_t start_remain = stream->start_len - stream->start_read;
872
+ int total = 0, error;
873
+
874
+ /*
875
+ * if we read more than just the header in the initial read, play
876
+ * that back for the caller.
877
+ */
878
+ if (start_remain && buffer_len) {
879
+ size_t chunk = min(start_remain, buffer_len);
880
+ memcpy(buffer, stream->start + stream->start_read, chunk);
881
+
882
+ buffer += chunk;
883
+ stream->start_read += chunk;
884
+
885
+ total += chunk;
886
+ buffer_len -= chunk;
887
+ }
888
+
889
+ if (buffer_len) {
890
+ size_t chunk = min(buffer_len, INT_MAX);
891
+
892
+ if ((error = git_zstream_get_output(buffer, &chunk, &stream->zstream)) < 0)
893
+ return error;
894
+
895
+ total += chunk;
896
+ }
897
+
898
+ return total;
899
+ }
900
+
901
+ static void loose_backend__readstream_free(git_odb_stream *_stream)
902
+ {
903
+ loose_readstream *stream = (loose_readstream *)_stream;
904
+
905
+ git_futils_mmap_free(&stream->map);
906
+ git_zstream_free(&stream->zstream);
907
+ git__free(stream);
908
+ }
909
+
910
+ static int loose_backend__readstream_packlike(
911
+ obj_hdr *hdr,
912
+ loose_readstream *stream)
913
+ {
914
+ const unsigned char *data;
915
+ size_t data_len, head_len;
916
+ int error;
917
+
918
+ data = stream->map.data;
919
+ data_len = stream->map.len;
920
+
921
+ /*
922
+ * read the object header, which is an (uncompressed)
923
+ * binary encoding of the object type and size.
924
+ */
925
+ if ((error = parse_header_packlike(hdr, &head_len, data, data_len)) < 0)
926
+ return error;
927
+
928
+ if (!git_object_typeisloose(hdr->type)) {
929
+ giterr_set(GITERR_ODB, "failed to inflate loose object");
930
+ return -1;
931
+ }
932
+
933
+ return git_zstream_set_input(&stream->zstream,
934
+ data + head_len, data_len - head_len);
935
+ }
936
+
937
+ static int loose_backend__readstream_standard(
938
+ obj_hdr *hdr,
939
+ loose_readstream *stream)
940
+ {
941
+ unsigned char head[MAX_HEADER_LEN];
942
+ size_t init, head_len;
943
+ int error;
944
+
945
+ if ((error = git_zstream_set_input(&stream->zstream,
946
+ stream->map.data, stream->map.len)) < 0)
947
+ return error;
948
+
949
+ init = sizeof(head);
950
+
951
+ /*
952
+ * inflate the initial part of the compressed buffer in order to
953
+ * parse the header; read the largest header possible, then store
954
+ * it in the `start` field of the stream object.
955
+ */
956
+ if ((error = git_zstream_get_output(head, &init, &stream->zstream)) < 0 ||
957
+ (error = parse_header(hdr, &head_len, head, init)) < 0)
958
+ return error;
959
+
960
+ if (!git_object_typeisloose(hdr->type)) {
961
+ giterr_set(GITERR_ODB, "failed to inflate disk object");
962
+ return -1;
963
+ }
964
+
965
+ if (init > head_len) {
966
+ stream->start_len = init - head_len;
967
+ memcpy(stream->start, head + head_len, init - head_len);
968
+ }
969
+
970
+ return 0;
971
+ }
972
+
973
+ static int loose_backend__readstream(
974
+ git_odb_stream **stream_out,
975
+ size_t *len_out,
976
+ git_otype *type_out,
977
+ git_odb_backend *_backend,
978
+ const git_oid *oid)
979
+ {
980
+ loose_backend *backend;
981
+ loose_readstream *stream = NULL;
982
+ git_hash_ctx *hash_ctx = NULL;
983
+ git_buf object_path = GIT_BUF_INIT;
984
+ obj_hdr hdr;
985
+ int error = 0;
986
+
987
+ assert(stream_out && len_out && type_out && _backend && oid);
988
+
989
+ backend = (loose_backend *)_backend;
990
+ *stream_out = NULL;
991
+ *len_out = 0;
992
+ *type_out = GIT_OBJ_BAD;
993
+
994
+ if (locate_object(&object_path, backend, oid) < 0) {
995
+ error = git_odb__error_notfound("no matching loose object",
996
+ oid, GIT_OID_HEXSZ);
997
+ goto done;
998
+ }
999
+
1000
+ stream = git__calloc(1, sizeof(loose_readstream));
1001
+ GITERR_CHECK_ALLOC(stream);
1002
+
1003
+ hash_ctx = git__malloc(sizeof(git_hash_ctx));
1004
+ GITERR_CHECK_ALLOC(hash_ctx);
1005
+
1006
+ if ((error = git_hash_ctx_init(hash_ctx)) < 0 ||
1007
+ (error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
1008
+ (error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
1009
+ goto done;
1010
+
1011
+ /* check for a packlike loose object */
1012
+ if (!is_zlib_compressed_data(stream->map.data, stream->map.len))
1013
+ error = loose_backend__readstream_packlike(&hdr, stream);
1014
+ else
1015
+ error = loose_backend__readstream_standard(&hdr, stream);
1016
+
1017
+ if (error < 0)
1018
+ goto done;
1019
+
1020
+ stream->stream.backend = _backend;
1021
+ stream->stream.hash_ctx = hash_ctx;
1022
+ stream->stream.read = &loose_backend__readstream_read;
1023
+ stream->stream.free = &loose_backend__readstream_free;
1024
+
1025
+ *stream_out = (git_odb_stream *)stream;
1026
+ *len_out = hdr.size;
1027
+ *type_out = hdr.type;
1028
+
1029
+ done:
1030
+ if (error < 0) {
1031
+ git_futils_mmap_free(&stream->map);
1032
+ git_zstream_free(&stream->zstream);
1033
+ git_hash_ctx_cleanup(hash_ctx);
1034
+ git__free(hash_ctx);
1035
+ git__free(stream);
1036
+ }
1037
+
1038
+ git_buf_free(&object_path);
1039
+ return error;
1040
+ }
1041
+
899
1042
  static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type)
900
1043
  {
901
- int error = 0, header_len;
1044
+ int error = 0;
902
1045
  git_buf final_path = GIT_BUF_INIT;
903
- char header[64];
1046
+ char header[MAX_HEADER_LEN];
1047
+ size_t header_len;
904
1048
  git_filebuf fbuf = GIT_FILEBUF_INIT;
905
1049
  loose_backend *backend;
906
1050
 
907
1051
  backend = (loose_backend *)_backend;
908
1052
 
909
1053
  /* prepare the header for the file */
910
- header_len = git_odb__format_object_header(header, sizeof(header), len, type);
1054
+ if ((error = git_odb__format_object_header(&header_len,
1055
+ header, sizeof(header), len, type)) < 0)
1056
+ goto cleanup;
911
1057
 
912
1058
  if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
913
1059
  git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
@@ -1002,7 +1148,8 @@ int git_odb_backend_loose(
1002
1148
  backend->parent.write = &loose_backend__write;
1003
1149
  backend->parent.read_prefix = &loose_backend__read_prefix;
1004
1150
  backend->parent.read_header = &loose_backend__read_header;
1005
- backend->parent.writestream = &loose_backend__stream;
1151
+ backend->parent.writestream = &loose_backend__writestream;
1152
+ backend->parent.readstream = &loose_backend__readstream;
1006
1153
  backend->parent.exists = &loose_backend__exists;
1007
1154
  backend->parent.exists_prefix = &loose_backend__exists_prefix;
1008
1155
  backend->parent.foreach = &loose_backend__foreach;