]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pack-write: fix return parameter of `write_rev_file_order()`
authorPatrick Steinhardt <ps@pks.im>
Mon, 30 Sep 2024 09:14:08 +0000 (11:14 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 30 Sep 2024 18:23:08 +0000 (11:23 -0700)
While the return parameter of `write_rev_file_order()` is a string
constant, the function may indeed return an allocated string when its
first parameter is a `NULL` pointer. This makes for a confusing calling
convention, where callers need to be aware of these intricate ownership
rules and cast away the constness to free the string in some cases.

Adapt the function and its caller `write_rev_file()` to always return an
allocated string and adapt callers to always free the return value.

Note that this requires us to also adapt `rename_tmp_packfile()`, which
compares the pointers to packfile data with each other. Now that the
path of the reverse index file gets allocated unconditionally the check
will always fail. This is fixed by using strcmp(3P) instead, which also
feels way less fragile.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/index-pack.c
midx-write.c
pack-write.c
pack.h
t/t5327-multi-pack-bitmaps-rev.sh

index e228c56ff2701b5e70fcb57962e4af6979dd809f..9d23b41b3a23067d4f16a3a84deec7af2bc82d86 100644 (file)
@@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name,
                                struct strbuf *name, unsigned char *hash,
                                const char *ext, int make_read_only_if_same)
 {
-       if (*final_name != curr_name) {
+       if (!*final_name || strcmp(*final_name, curr_name)) {
                if (!*final_name)
                        *final_name = odb_pack_name(name, hash, ext);
                if (finalize_object_file(curr_name, *final_name))
@@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc,
 {
        int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
        const char *curr_index;
-       const char *curr_rev_index = NULL;
+       char *curr_rev_index = NULL;
        const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
        const char *keep_msg = NULL;
        const char *promisor_msg = NULL;
@@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc,
                free((void *) curr_pack);
        if (!index_name)
                free((void *) curr_index);
-       if (!rev_index_name)
-               free((void *) curr_rev_index);
+       free(curr_rev_index);
 
        /*
         * Let the caller know this pack is not self contained
index 625c7d31371201150c8a6a87a60f9f9ec1e9856b..b3a5f6c51669349dc26edf94b5c25b8fea033322 100644 (file)
@@ -649,7 +649,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
                                     struct write_midx_context *ctx)
 {
        struct strbuf buf = STRBUF_INIT;
-       const char *tmp_file;
+       char *tmp_file;
 
        trace2_region_enter("midx", "write_midx_reverse_index", the_repository);
 
@@ -662,6 +662,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
                die(_("cannot store reverse index file"));
 
        strbuf_release(&buf);
+       free(tmp_file);
 
        trace2_region_leave("midx", "write_midx_reverse_index", the_repository);
 }
index 27965672f17822c342206b1c2518f76debd2b012..9961149e65f0f7104eace1b56cd1857c82fba882 100644 (file)
@@ -212,15 +212,15 @@ static void write_rev_trailer(struct hashfile *f, const unsigned char *hash)
        hashwrite(f, hash, the_hash_algo->rawsz);
 }
 
-const char *write_rev_file(const char *rev_name,
-                          struct pack_idx_entry **objects,
-                          uint32_t nr_objects,
-                          const unsigned char *hash,
-                          unsigned flags)
+char *write_rev_file(const char *rev_name,
+                    struct pack_idx_entry **objects,
+                    uint32_t nr_objects,
+                    const unsigned char *hash,
+                    unsigned flags)
 {
        uint32_t *pack_order;
        uint32_t i;
-       const char *ret;
+       char *ret;
 
        if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY))
                return NULL;
@@ -238,13 +238,14 @@ const char *write_rev_file(const char *rev_name,
        return ret;
 }
 
-const char *write_rev_file_order(const char *rev_name,
-                                uint32_t *pack_order,
-                                uint32_t nr_objects,
-                                const unsigned char *hash,
-                                unsigned flags)
+char *write_rev_file_order(const char *rev_name,
+                          uint32_t *pack_order,
+                          uint32_t nr_objects,
+                          const unsigned char *hash,
+                          unsigned flags)
 {
        struct hashfile *f;
+       char *path;
        int fd;
 
        if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
@@ -254,12 +255,13 @@ const char *write_rev_file_order(const char *rev_name,
                if (!rev_name) {
                        struct strbuf tmp_file = STRBUF_INIT;
                        fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX");
-                       rev_name = strbuf_detach(&tmp_file, NULL);
+                       path = strbuf_detach(&tmp_file, NULL);
                } else {
                        unlink(rev_name);
                        fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
+                       path = xstrdup(rev_name);
                }
-               f = hashfd(fd, rev_name);
+               f = hashfd(fd, path);
        } else if (flags & WRITE_REV_VERIFY) {
                struct stat statbuf;
                if (stat(rev_name, &statbuf)) {
@@ -270,22 +272,24 @@ const char *write_rev_file_order(const char *rev_name,
                                die_errno(_("could not stat: %s"), rev_name);
                }
                f = hashfd_check(rev_name);
-       } else
+               path = xstrdup(rev_name);
+       } else {
                return NULL;
+       }
 
        write_rev_header(f);
 
        write_rev_index_positions(f, pack_order, nr_objects);
        write_rev_trailer(f, hash);
 
-       if (rev_name && adjust_shared_perm(rev_name) < 0)
-               die(_("failed to make %s readable"), rev_name);
+       if (adjust_shared_perm(path) < 0)
+               die(_("failed to make %s readable"), path);
 
        finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
                          CSUM_HASH_IN_STREAM | CSUM_CLOSE |
                          ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
 
-       return rev_name;
+       return path;
 }
 
 static void write_mtimes_header(struct hashfile *f)
@@ -549,7 +553,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
                         unsigned char hash[],
                         char **idx_tmp_name)
 {
-       const char *rev_tmp_name = NULL;
+       char *rev_tmp_name = NULL;
        char *mtimes_tmp_name = NULL;
 
        if (adjust_shared_perm(pack_tmp_name))
@@ -575,7 +579,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
        if (mtimes_tmp_name)
                rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
 
-       free((char *)rev_tmp_name);
+       free(rev_tmp_name);
        free(mtimes_tmp_name);
 }
 
diff --git a/pack.h b/pack.h
index 3ab9e3f60c0b0341c3cb37e9026bdc217ba6aa97..02bbdfb19cc030b5b01ad39693876916a33df183 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -96,8 +96,8 @@ struct ref;
 
 void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);
 
-const char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
-const char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
+char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
+char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
 
 /*
  * The "hdr" output buffer should be at least this big, which will handle sizes
index 9cac03a94bf4b4014d0ecd9fd7fc6320949b3e9f..994a8e6be464ac08982e806874fdc865ec3ab078 100755 (executable)
@@ -2,6 +2,7 @@
 
 test_description='exercise basic multi-pack bitmap functionality (.rev files)'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "${TEST_DIRECTORY}/lib-bitmap.sh"