]> git.ipfire.org Git - thirdparty/git.git/commitdiff
combine-diff: fix leaking lost lines
authorPatrick Steinhardt <ps@pks.im>
Tue, 5 Nov 2024 06:17:28 +0000 (07:17 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 Nov 2024 06:37:55 +0000 (22:37 -0800)
The `cnt` variable tracks the number of lines in a patch diff. It can
happen though that there are no newlines, in which case we'd still end
up allocating our array of `sline`s. In fact, we always allocate it with
`cnt + 2` entries: one extra entry for the deletion hunk at the end, and
another entry that we don't seem to ever populate at all but acts as a
kind of sentinel value.

When we loop through the array to clear it at the end of this function
we only loop until `lno < cnt`, and thus we may not end up releasing
whatever the two extra `sline`s contain. While that shouldn't matter for
the sentinel value, it does matter for the extra deletion hunk sline.
Regardless of that, plug this memory leak by releasing both extra
entries, which makes the logic a bit easier to reason about.

While at it, fix the formatting of a local comment, which incidentally
also provides the necessary context for why we overallocate the `sline`
array.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
combine-diff.c
t/t4038-diff-combined.sh

index f6b624dc288d72bde9c4947b892a2fca684ca824..33d0ed7097569c57247f68c1f995a0bb23be0afa 100644 (file)
@@ -1185,7 +1185,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
        result_file.ptr = result;
        result_file.size = result_size;
 
-       /* Even p_lno[cnt+1] is valid -- that is for the end line number
+       /*
+        * Even p_lno[cnt+1] is valid -- that is for the end line number
         * for deletion hunk at the end.
         */
        CALLOC_ARRAY(sline[0].p_lno, st_mult(st_add(cnt, 2), num_parent));
@@ -1220,7 +1221,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
        }
        free(result);
 
-       for (lno = 0; lno < cnt; lno++) {
+       for (lno = 0; lno < cnt + 2; lno++) {
                if (sline[lno].lost) {
                        struct lline *ll = sline[lno].lost;
                        while (ll) {
index 2ce26e585c98c1a3045dee4545763f160f59aa82..00190802d831f032fd936b3fe11ad5661dfb6ca5 100755 (executable)
@@ -5,6 +5,7 @@ test_description='combined diff'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-diff.sh