resolve_ref() may return a pointer to a static buffer. Callers that use this value outside of a block should copy the value to avoid some hidden resolve_ref() call that may change the static buffer's value. The bug found by Tony Wang <wwwjfy@xxxxxxxxx> in builtin/merge.c demonstrates this. The first call is in cmd_merge() branch = resolve_ref("HEAD", head_sha1, 0, &flag); Then deep in lookup_commit_or_die() a few lines after, resolve_ref() may be called again and destroy "branch". lookup_commit_or_die lookup_commit_reference lookup_commit_reference_gently parse_object lookup_replace_object do_lookup_replace_object prepare_replace_object for_each_replace_ref do_for_each_ref get_loose_refs get_ref_dir get_ref_dir resolve_ref Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/checkout.c | 4 +++- builtin/commit.c | 3 ++- builtin/fmt-merge-msg.c | 1 + builtin/merge.c | 7 +++++-- builtin/notes.c | 1 + builtin/receive-pack.c | 2 ++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index 2a80772..98ddbcd 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -699,7 +699,9 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new) unsigned char rev[20]; int flag; memset(&old, 0, sizeof(old)); - old.path = xstrdup(resolve_ref("HEAD", rev, 0, &flag)); + old.path = resolve_ref("HEAD", rev, 0, &flag); + if (old.path) + old.path = xstrdup(old.path); old.commit = lookup_commit_reference_gently(rev, 1); if (!(flag & REF_ISSYMREF)) { free((char *)old.path); diff --git a/builtin/commit.c b/builtin/commit.c index c46f2d1..f3a6ed2 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1259,7 +1259,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1, struct commit *commit; struct strbuf format = STRBUF_INIT; unsigned char junk_sha1[20]; - const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL); + const char *head; struct pretty_print_context pctx = {0}; struct strbuf author_ident = STRBUF_INIT; struct strbuf committer_ident = STRBUF_INIT; @@ -1304,6 +1304,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1, rev.diffopt.break_opt = 0; diff_setup_done(&rev.diffopt); + head = resolve_ref("HEAD", junk_sha1, 0, NULL); printf("[%s%s ", !prefixcmp(head, "refs/heads/") ? head + 11 : diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 7e2f225..cab50e0 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -268,6 +268,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in, die("No current branch"); if (!prefixcmp(current_branch, "refs/heads/")) current_branch += 11; + current_branch = xstrdup(current_branch); /* get a line */ while (pos < in->len) { diff --git a/builtin/merge.c b/builtin/merge.c index dffd5ec..6865cb7 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1096,8 +1096,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * current branch. */ branch = resolve_ref("HEAD", head_sha1, 0, &flag); - if (branch && !prefixcmp(branch, "refs/heads/")) - branch += 11; + if (branch) { + if (!prefixcmp(branch, "refs/heads/")) + branch += 11; + branch = xstrdup(branch); + } if (!branch || is_null_sha1(head_sha1)) head_commit = NULL; else diff --git a/builtin/notes.c b/builtin/notes.c index f8e437d..c6e4c86 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -828,6 +828,7 @@ static int merge_commit(struct notes_merge_options *o) o->local_ref = resolve_ref("NOTES_MERGE_REF", sha1, 0, NULL); if (!o->local_ref) die("Failed to resolve NOTES_MERGE_REF"); + o->local_ref = xstrdup(o->local_ref); if (notes_merge_commit(o, t, partial, sha1)) die("Failed to finalize notes merge"); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 7ec68a1..6065bf0 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -696,6 +696,8 @@ static void execute_commands(struct command *commands, const char *unpacker_erro check_aliased_updates(commands); head_name = resolve_ref("HEAD", sha1, 0, NULL); + if (head_name) + head_name = xstrdup(head_name); for (cmd = commands; cmd; cmd = cmd->next) if (!cmd->skip_update) -- 1.7.3.1.256.g2539c.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html