index-pack: make pointer-alias fallbacks safer

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@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2017-03-16 10:27:20 -04:00 committed by Junio C Hamano
parent ba47a3088f
commit f20754802a

View File

@ -1386,7 +1386,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
unsigned char *sha1) unsigned char *sha1)
{ {
const char *report = "pack"; 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; int err;
if (!from_stdin) { 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); int keep_fd, keep_msg_len = strlen(keep_msg);
if (!keep_name) 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 (keep_fd < 0) {
if (errno != EEXIST) if (errno != EEXIST)
die_errno(_("cannot write keep file '%s'"), die_errno(_("cannot write keep file '%s'"),
keep_name ? keep_name : name.buf); keep_name);
} else { } else {
if (keep_msg_len > 0) { if (keep_msg_len > 0) {
write_or_die(keep_fd, keep_msg, keep_msg_len); 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) if (close(keep_fd) != 0)
die_errno(_("cannot close written keep file '%s'"), die_errno(_("cannot close written keep file '%s'"),
keep_name ? keep_name : name.buf); keep_name);
report = "keep"; report = "keep";
} }
} }
if (final_pack_name != curr_pack_name) { if (final_pack_name != curr_pack_name) {
if (!final_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)) if (finalize_object_file(curr_pack_name, final_pack_name))
die(_("cannot store pack file")); die(_("cannot store pack file"));
} else if (from_stdin) } 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 != curr_index_name) {
if (!final_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)) if (finalize_object_file(curr_index_name, final_index_name))
die(_("cannot store index file")); die(_("cannot store index file"));
} else } 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) static int git_index_pack_config(const char *k, const char *v, void *cb)