Copy resolve_ref() return value for longer use

resolve_ref() may return a pointer to a static buffer. Callers that
use this value longer than a couple of statements 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@gmail.com> 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

All call sites are checked and made sure that xstrdup() is called if
the value should be saved.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy
2011-11-13 17:22:15 +07:00
committed by Junio C Hamano
parent c689332391
commit d5a35c114a
8 changed files with 66 additions and 28 deletions

View File

@ -695,7 +695,10 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
check_aliased_updates(commands);
free((char *)head_name);
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)