]> git.ipfire.org Git - thirdparty/git.git/commitdiff
diffcore-order: fix leaking buffer when parsing orderfiles
authorPatrick Steinhardt <ps@pks.im>
Thu, 26 Sep 2024 11:46:37 +0000 (13:46 +0200)
committerJunio C Hamano <gitster@pobox.com>
Fri, 27 Sep 2024 15:25:35 +0000 (08:25 -0700)
In `prepare_order()` we parse an orderfile and assign it to a global
array. In order to save on some allocations, we replace newlines with
NUL characters and then assign pointers into the allocated buffer to
that array. This can cause the buffer to be completely unreferenced
though in some cases, e.g. because the order file is empty or because we
had to use `xmemdupz()` to copy the lines instead of NUL-terminating
them.

Refactor the code to always `xmemdupz()` the strings. This is a bit
simpler, and it is rather unlikely that saving a handful of allocations
really matters. This allows us to release the string buffer and thus
plug the memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diffcore-order.c
t/t4056-diff-order.sh
t/t4204-patch-id.sh

index e7d20ebd2d1b45b073ac2825b9371986d305ee29..912513d3e67a9b277dd24a93992c456a061b196f 100644 (file)
@@ -14,8 +14,7 @@ static void prepare_order(const char *orderfile)
 {
        int cnt, pass;
        struct strbuf sb = STRBUF_INIT;
-       void *map;
-       char *cp, *endp;
+       const char *cp, *endp;
        ssize_t sz;
 
        if (order)
@@ -24,14 +23,13 @@ static void prepare_order(const char *orderfile)
        sz = strbuf_read_file(&sb, orderfile, 0);
        if (sz < 0)
                die_errno(_("failed to read orderfile '%s'"), orderfile);
-       map = strbuf_detach(&sb, NULL);
-       endp = (char *) map + sz;
+       endp = sb.buf + sz;
 
        for (pass = 0; pass < 2; pass++) {
                cnt = 0;
-               cp = map;
+               cp = sb.buf;
                while (cp < endp) {
-                       char *ep;
+                       const char *ep;
                        for (ep = cp; ep < endp && *ep != '\n'; ep++)
                                ;
                        /* cp to ep has one line */
@@ -40,12 +38,7 @@ static void prepare_order(const char *orderfile)
                        else if (pass == 0)
                                cnt++;
                        else {
-                               if (*ep == '\n') {
-                                       *ep = 0;
-                                       order[cnt] = cp;
-                               } else {
-                                       order[cnt] = xmemdupz(cp, ep - cp);
-                               }
+                               order[cnt] = xmemdupz(cp, ep - cp);
                                cnt++;
                        }
                        if (ep < endp)
@@ -57,6 +50,8 @@ static void prepare_order(const char *orderfile)
                        ALLOC_ARRAY(order, cnt);
                }
        }
+
+       strbuf_release(&sb);
 }
 
 static int match_order(const char *path)
index aec1d9d1b42f65f1080f7e054bca70bbffcefcc6..32c5fcb9a27c2e0156ec5db3adadc038468f2ee4 100755 (executable)
@@ -5,6 +5,7 @@ test_description='diff order & rotate'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 create_files () {
index dc8ddb10affcea6deae823fbba39903a183060b2..c0a4a02dcfa3fda6a8dc27e61c2f664df4d7aac0 100755 (executable)
@@ -5,6 +5,7 @@ test_description='git patch-id'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '