hashwrite() takes the byte count as "uint32_t" on all platforms. When
pack-objects writes the entire compressed buffer of an object in a
single call, which can exceed 4GiB if the object is in memory, poorly
compressible and core.bigFileThreshold is raised accordingly, it writes
only "count mod 2^32" bytes, corrupting the pack.
This was verified using a 16-bit simulation, where "git cat-file" and
"git fsck" failed after "git repack -a -d" with "offset beyond end of
packfile (truncated pack?)".
Make the count parameter of hashwrite() a "size_t". The internal loop
already handles writing in buffer-sized blocks.
Triggering this requires processing an object of 4GiB or more, so no
test is added.
Signed-off-by: Elia Pinto <redacted>
---
csum-file.c | 2 +-
csum-file.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/csum-file.c b/csum-file.c
index fe18ee1de3..26aa662637 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -102,7 +102,7 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result,
return fd;
}
-void hashwrite(struct hashfile *f, const void *buf, uint32_t count)
+void hashwrite(struct hashfile *f, const void *buf, size_t count)
{
while (count) {
unsigned left = f->buffer_len - f->offset;diff --git a/csum-file.h b/csum-file.h
index 6ed74d1637..f1c8a9df13 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -75,7 +75,7 @@ void free_hashfile(struct hashfile *f);
* Finalize the hashfile by flushing data to disk and free'ing it.
*/
int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
-void hashwrite(struct hashfile *, const void *, uint32_t);
+void hashwrite(struct hashfile *, const void *, size_t);
void hashflush(struct hashfile *f);
void crc32_begin(struct hashfile *);
uint32_t crc32_end(struct hashfile *);
--
2.53.0