Skip to content

Commit 2f0ee05

Browse files
pks-tgitster
authored andcommitted
pack-write: fix return parameter of write_rev_file_order()
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6512d6e commit 2f0ee05

File tree

5 files changed

+31
-26
lines changed

5 files changed

+31
-26
lines changed

builtin/index-pack.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name,
15051505
struct strbuf *name, unsigned char *hash,
15061506
const char *ext, int make_read_only_if_same)
15071507
{
1508-
if (*final_name != curr_name) {
1508+
if (!*final_name || strcmp(*final_name, curr_name)) {
15091509
if (!*final_name)
15101510
*final_name = odb_pack_name(name, hash, ext);
15111511
if (finalize_object_file(curr_name, *final_name))
@@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc,
17261726
{
17271727
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
17281728
const char *curr_index;
1729-
const char *curr_rev_index = NULL;
1729+
char *curr_rev_index = NULL;
17301730
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
17311731
const char *keep_msg = NULL;
17321732
const char *promisor_msg = NULL;
@@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc,
19681968
free((void *) curr_pack);
19691969
if (!index_name)
19701970
free((void *) curr_index);
1971-
if (!rev_index_name)
1972-
free((void *) curr_rev_index);
1971+
free(curr_rev_index);
19731972

19741973
/*
19751974
* Let the caller know this pack is not self contained

midx-write.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
649649
struct write_midx_context *ctx)
650650
{
651651
struct strbuf buf = STRBUF_INIT;
652-
const char *tmp_file;
652+
char *tmp_file;
653653

654654
trace2_region_enter("midx", "write_midx_reverse_index", the_repository);
655655

@@ -662,6 +662,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
662662
die(_("cannot store reverse index file"));
663663

664664
strbuf_release(&buf);
665+
free(tmp_file);
665666

666667
trace2_region_leave("midx", "write_midx_reverse_index", the_repository);
667668
}

pack-write.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,15 @@ static void write_rev_trailer(struct hashfile *f, const unsigned char *hash)
212212
hashwrite(f, hash, the_hash_algo->rawsz);
213213
}
214214

215-
const char *write_rev_file(const char *rev_name,
216-
struct pack_idx_entry **objects,
217-
uint32_t nr_objects,
218-
const unsigned char *hash,
219-
unsigned flags)
215+
char *write_rev_file(const char *rev_name,
216+
struct pack_idx_entry **objects,
217+
uint32_t nr_objects,
218+
const unsigned char *hash,
219+
unsigned flags)
220220
{
221221
uint32_t *pack_order;
222222
uint32_t i;
223-
const char *ret;
223+
char *ret;
224224

225225
if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY))
226226
return NULL;
@@ -238,13 +238,14 @@ const char *write_rev_file(const char *rev_name,
238238
return ret;
239239
}
240240

241-
const char *write_rev_file_order(const char *rev_name,
242-
uint32_t *pack_order,
243-
uint32_t nr_objects,
244-
const unsigned char *hash,
245-
unsigned flags)
241+
char *write_rev_file_order(const char *rev_name,
242+
uint32_t *pack_order,
243+
uint32_t nr_objects,
244+
const unsigned char *hash,
245+
unsigned flags)
246246
{
247247
struct hashfile *f;
248+
char *path;
248249
int fd;
249250

250251
if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
@@ -254,12 +255,13 @@ const char *write_rev_file_order(const char *rev_name,
254255
if (!rev_name) {
255256
struct strbuf tmp_file = STRBUF_INIT;
256257
fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX");
257-
rev_name = strbuf_detach(&tmp_file, NULL);
258+
path = strbuf_detach(&tmp_file, NULL);
258259
} else {
259260
unlink(rev_name);
260261
fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
262+
path = xstrdup(rev_name);
261263
}
262-
f = hashfd(fd, rev_name);
264+
f = hashfd(fd, path);
263265
} else if (flags & WRITE_REV_VERIFY) {
264266
struct stat statbuf;
265267
if (stat(rev_name, &statbuf)) {
@@ -270,22 +272,24 @@ const char *write_rev_file_order(const char *rev_name,
270272
die_errno(_("could not stat: %s"), rev_name);
271273
}
272274
f = hashfd_check(rev_name);
273-
} else
275+
path = xstrdup(rev_name);
276+
} else {
274277
return NULL;
278+
}
275279

276280
write_rev_header(f);
277281

278282
write_rev_index_positions(f, pack_order, nr_objects);
279283
write_rev_trailer(f, hash);
280284

281-
if (rev_name && adjust_shared_perm(rev_name) < 0)
282-
die(_("failed to make %s readable"), rev_name);
285+
if (adjust_shared_perm(path) < 0)
286+
die(_("failed to make %s readable"), path);
283287

284288
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
285289
CSUM_HASH_IN_STREAM | CSUM_CLOSE |
286290
((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
287291

288-
return rev_name;
292+
return path;
289293
}
290294

291295
static void write_mtimes_header(struct hashfile *f)
@@ -549,7 +553,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
549553
unsigned char hash[],
550554
char **idx_tmp_name)
551555
{
552-
const char *rev_tmp_name = NULL;
556+
char *rev_tmp_name = NULL;
553557
char *mtimes_tmp_name = NULL;
554558

555559
if (adjust_shared_perm(pack_tmp_name))
@@ -575,7 +579,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
575579
if (mtimes_tmp_name)
576580
rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
577581

578-
free((char *)rev_tmp_name);
582+
free(rev_tmp_name);
579583
free(mtimes_tmp_name);
580584
}
581585

pack.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ struct ref;
9696

9797
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);
9898

99-
const char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
100-
const char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
99+
char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
100+
char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
101101

102102
/*
103103
* The "hdr" output buffer should be at least this big, which will handle sizes

t/t5327-multi-pack-bitmaps-rev.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
test_description='exercise basic multi-pack bitmap functionality (.rev files)'
44

5+
TEST_PASSES_SANITIZE_LEAK=true
56
. ./test-lib.sh
67
. "${TEST_DIRECTORY}/lib-bitmap.sh"
78

0 commit comments

Comments
 (0)