On 16/03/17 14:27, Jeff King wrote: > The final() function accepts a NULL value for certain > parameters, and falls back to writing into a reusable "name" > buffer, and then either: > > 1. For "keep_name", requiring all uses to do "keep_name ? > keep_name : name.buf". This is awkward, and it's easy > to accidentally look at the maybe-NULL keep_name. > > 2. For "final_index_name" and "final_pack_name", aliasing > those pointers to the "name" buffer. This is easier to > use, but the aliased pointers become invalid after the > buffer is reused (this isn't a bug now, but it's a > potential pitfall). > > One way to make this safer would be to introduce an extra > pointer to do the aliasing, and have its lifetime match the > validity of the "name" buffer. But it's still easy to > accidentally use the wrong name (i.e., to use > "final_pack_name" instead of the aliased pointer). > > Instead, let's use three separate buffers that will remain > valid through the function. That makes it safe to alias the > pointers and use them consistently. The extra allocations > shouldn't matter, as this function is not performance > sensitive. > > Signed-off-by: Jeff King <peff@xxxxxxxx> > --- > builtin/index-pack.c | 20 ++++++++++++-------- > 1 file changed, 12 insertions(+), 8 deletions(-) > > diff --git a/builtin/index-pack.c b/builtin/index-pack.c > index dcb346ab7..88d205f85 100644 > --- a/builtin/index-pack.c > +++ b/builtin/index-pack.c > @@ -1386,7 +1386,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name, > unsigned char *sha1) > { > const char *report = "pack"; > - struct strbuf name = STRBUF_INIT; > + struct strbuf pack_name = STRBUF_INIT; > + struct strbuf index_name = STRBUF_INIT; > + struct strbuf keep_name_buf = STRBUF_INIT; > int err; > > if (!from_stdin) { > @@ -1402,13 +1404,13 @@ static void final(const char *final_pack_name, const char *curr_pack_name, > int keep_fd, keep_msg_len = strlen(keep_msg); > > if (!keep_name) > - odb_pack_name(&name, sha1, "keep"); > + keep_name = odb_pack_name(&keep_name_buf, sha1, "keep"); > > - keep_fd = odb_pack_keep(keep_name ? keep_name : name.buf); > + keep_fd = odb_pack_keep(keep_name); > if (keep_fd < 0) { > if (errno != EEXIST) > die_errno(_("cannot write keep file '%s'"), > - keep_name ? keep_name : name.buf); > + keep_name); > } else { > if (keep_msg_len > 0) { > write_or_die(keep_fd, keep_msg, keep_msg_len); > @@ -1416,14 +1418,14 @@ static void final(const char *final_pack_name, const char *curr_pack_name, > } > if (close(keep_fd) != 0) > die_errno(_("cannot close written keep file '%s'"), > - keep_name ? keep_name : name.buf); > + keep_name); > report = "keep"; > } > } > > if (final_pack_name != curr_pack_name) { > if (!final_pack_name) > - final_pack_name = odb_pack_name(&name, sha1, "pack"); > + final_pack_name = odb_pack_name(&pack_name, sha1, "pack"); > if (finalize_object_file(curr_pack_name, final_pack_name)) > die(_("cannot store pack file")); > } else if (from_stdin) > @@ -1431,7 +1433,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, > > if (final_index_name != curr_index_name) { > if (!final_index_name) > - final_index_name = odb_pack_name(&name, sha1, "idx"); > + final_index_name = odb_pack_name(&index_name, sha1, "idx"); > if (finalize_object_file(curr_index_name, final_index_name)) > die(_("cannot store index file")); > } else > @@ -1458,7 +1460,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name, > } > } > > - strbuf_release(&name); > + strbuf_release(&index_name); > + strbuf_release(&pack_name); > + strbuf_release(&keep_name_buf); > } > > static int git_index_pack_config(const char *k, const char *v, void *cb) > Yep, much better. ATB, Ramsay Jones