bulk-checkin: fix leaking state TODO

When flushing a bulk-checking to disk we also reset the `struct bulk_checkin_packfile` state. But while we free some of its members, others aren't being free'd, leading to memory leaks: - The temporary packfile name is not getting freed. - The `struct hashfile` only gets freed in case we end up calling `finalize_hashfile()`. There are code paths though where that is not the case, namely when nothing has been written. For this, we need to make `free_hashfile()` public. Fix those leaks. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 14, 2024 at 08:52 UTC c81dcf630cec64d0042f08f7210300671ed5b926
4 files changed +14 -1
bulk-checkin.c
+2
@@ -61,6 +61,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
61
62 if (state->nr_written == 0) {
63 close(state->f->fd);
64 + free_hashfile(state->f);
65 unlink(state->pack_tmp_name);
66 goto clear_exit;
67 } else if (state->nr_written == 1) {
@@ -83,6 +84,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
84 free(state->written[i]);
85
86 clear_exit:
87 + free(state->pack_tmp_name);
88 free(state->written);
89 memset(state, 0, sizeof(*state));
90
csum-file.c
+1 -1
@@ -56,7 +56,7 @@ void hashflush(struct hashfile *f)
56 }
57 }
58
59 -static void free_hashfile(struct hashfile *f)
59 +void free_hashfile(struct hashfile *f)
60 {
61 free(f->buffer);
62 free(f->check_buffer);
csum-file.h
+10
@@ -46,6 +46,16 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
46 struct hashfile *hashfd(int fd, const char *name);
47 struct hashfile *hashfd_check(const char *name);
48 struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
49 +
50 +/*
51 + * Free the hashfile without flushing its contents to disk. This only
52 + * needs to be called when not calling `finalize_hashfile()`.
53 + */
54 +void free_hashfile(struct hashfile *f);
55 +
56 +/*
57 + * Finalize the hashfile by flushing data to disk and free'ing it.
58 + */
59 int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
60 void hashwrite(struct hashfile *, const void *, unsigned int);
61 void hashflush(struct hashfile *f);
t/t1050-large.sh
+1
@@ -3,6 +3,7 @@
3
4 test_description='adding and checking out large blobs'
5
6 +TEST_PASSES_SANITIZE_LEAK=true
7 . ./test-lib.sh
8
9 test_expect_success 'core.bigFileThreshold must be non-negative' '