trailer: fix leaking strbufs when formatting trailers

When formatting trailer lines we iterate through each of the trailers and munge their respective token/value pairs according to the trailer options. When formatting a trailer that has its `item->token` pointer set we perform the munging in two local buffers. In the case where we figure out that the value is empty and `trim_empty` is set we just skip over the trailer item. But the buffers are local to the loop and we don't release their contents, leading to a memory leak. Plug this leak by lifting the buffers outside of the loop and releasing them on function return. This fixes the memory leaks, but also optimizes the loop as we don't have to reallocate the buffers on every single iteration. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 5, 2024 at 07:17 UTC ff31b7b941286d91d03ddf4faac22b99149ea4b1
2 files changed +8 -5
t/t7513-interpret-trailers.sh
+1
@@ -5,6 +5,7 @@
5
6 test_description='git interpret-trailers'
7
8 +TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
10
11 # When we want one trailing space at the end of each line, let's use sed
trailer.c
+7 -5
@@ -1111,6 +1111,8 @@ void format_trailers(const struct process_trailer_options *opts,
1111 struct list_head *trailers,
1112 struct strbuf *out)
1113 {
1114 + struct strbuf tok = STRBUF_INIT;
1115 + struct strbuf val = STRBUF_INIT;
1116 size_t origlen = out->len;
1117 struct list_head *pos;
1118 struct trailer_item *item;
@@ -1118,9 +1120,9 @@ void format_trailers(const struct process_trailer_options *opts,
1120 list_for_each(pos, trailers) {
1121 item = list_entry(pos, struct trailer_item, list);
1122 if (item->token) {
1121 - struct strbuf tok = STRBUF_INIT;
1122 - struct strbuf val = STRBUF_INIT;
1123 + strbuf_reset(&tok);
1124 strbuf_addstr(&tok, item->token);
1125 + strbuf_reset(&val);
1126 strbuf_addstr(&val, item->value);
1127
1128 /*
@@ -1151,9 +1153,6 @@ void format_trailers(const struct process_trailer_options *opts,
1153 if (!opts->separator)
1154 strbuf_addch(out, '\n');
1155 }
1154 - strbuf_release(&tok);
1155 - strbuf_release(&val);
1156 -
1156 } else if (!opts->only_trailers) {
1157 if (opts->separator && out->len != origlen) {
1158 strbuf_addbuf(out, opts->separator);
@@ -1165,6 +1164,9 @@ void format_trailers(const struct process_trailer_options *opts,
1164 strbuf_addch(out, '\n');
1165 }
1166 }
1167 +
1168 + strbuf_release(&tok);
1169 + strbuf_release(&val);
1170 }
1171
1172 void format_trailers_from_commit(const struct process_trailer_options *opts,