summaryrefslogtreecommitdiff
path: root/reflog-walk.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2017-07-07 08:43:16 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-07-07 16:04:34 (GMT)
commite30d463d450286ffafb442ecc7686df4004c06ff (patch)
tree10387528a64aa4361f8e19b8efa8e806cdd69eb0 /reflog-walk.c
parent8aae3cf7558f00cf3c05636f888cb11e5e548e51 (diff)
downloadgit-e30d463d450286ffafb442ecc7686df4004c06ff.zip
git-e30d463d450286ffafb442ecc7686df4004c06ff.tar.gz
git-e30d463d450286ffafb442ecc7686df4004c06ff.tar.bz2
reflog-walk: include all fields when freeing complete_reflogs
When we encounter an error adding reflogs for a walk, we try to free any logs we have read. But we didn't free all fields, meaning that we could in theory leak all of the "items" array (which would consitute the bulk of the allocated memory). This patch adds a helper which frees all of the entries and uses it as appropriate. As it turns out, the leak seems impossible to trigger with the current code. Of the three error paths that free the complete_reflogs struct, two only kick in when the items array is empty, and the third was removed entirely in the previous commit. So this patch should be a noop in terms of behavior, but it fixes a potential maintenance headache should anybody add a new error path and copy the partial-free code. Which is what happened in 5026b47175 (add_reflog_for_walk: avoid memory leak, 2017-05-04), though its leaky call was the third one that was recently removed. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'reflog-walk.c')
-rw-r--r--reflog-walk.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/reflog-walk.c b/reflog-walk.c
index 2a43537..ba72020 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -38,6 +38,22 @@ static int read_one_reflog(struct object_id *ooid, struct object_id *noid,
return 0;
}
+static void free_complete_reflog(struct complete_reflogs *array)
+{
+ int i;
+
+ if (!array)
+ return;
+
+ for (i = 0; i < array->nr; i++) {
+ free(array->items[i].email);
+ free(array->items[i].message);
+ }
+ free(array->items);
+ free(array->ref);
+ free(array);
+}
+
static struct complete_reflogs *read_complete_reflog(const char *ref)
{
struct complete_reflogs *reflogs =
@@ -189,20 +205,14 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
if (ret > 1)
free(b);
else if (ret == 1) {
- if (reflogs) {
- free(reflogs->ref);
- free(reflogs);
- }
+ free_complete_reflog(reflogs);
free(branch);
branch = b;
reflogs = read_complete_reflog(branch);
}
}
if (!reflogs || reflogs->nr == 0) {
- if (reflogs) {
- free(reflogs->ref);
- free(reflogs);
- }
+ free_complete_reflog(reflogs);
free(branch);
return -1;
}