create_symref(): do not assume pathname from git_path() persists long enough
authorJunio C Hamano <junkio@cox.net>
Sat, 27 Jan 2007 01:49:00 +0000 (17:49 -0800)
committerJunio C Hamano <junkio@cox.net>
Sun, 28 Jan 2007 10:16:46 +0000 (02:16 -0800)
Being lazy to rely on the cycling N buffers mkpath() and friends
return is nice in general, but it makes it too easy to introduce
new bugs that are "mysterious".

Introduction of read_ref() in create_symref() after calling
git_path() to get the git_HEAD value (i.e. the path to create a
new symref at) consumed more than the available buffers and
broke a later call to mkpath() that derives lockpath from it.

Signed-off-by: Junio C Hamano <junkio@cox.net>
refs.c

diff --git a/refs.c b/refs.c
index 591318501f6ba072c4888ed7cf9e5b34d26fb32f..4a523086e37fa0bcdd647c826b9221165d630586 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -992,7 +992,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
        const char *lockpath;
        char ref[1000];
        int fd, len, written;
-       const char *git_HEAD = git_path("%s", ref_target);
+       char *git_HEAD = xstrdup(git_path("%s", ref_target));
        unsigned char old_sha1[20], new_sha1[20];
 
        if (logmsg && read_ref(ref_target, old_sha1))
@@ -1010,36 +1010,38 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
        len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
        if (sizeof(ref) <= len) {
                error("refname too long: %s", refs_heads_master);
-               return -1;
+               goto error_free_return;
        }
        lockpath = mkpath("%s.lock", git_HEAD);
        fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
        if (fd < 0) {
                error("Unable to open %s for writing", lockpath);
-               return -5;
+               goto error_free_return;
        }
        written = write_in_full(fd, ref, len);
        close(fd);
        if (written != len) {
-               unlink(lockpath);
                error("Unable to write to %s", lockpath);
-               return -2;
+               goto error_unlink_return;
        }
        if (rename(lockpath, git_HEAD) < 0) {
-               unlink(lockpath);
                error("Unable to create %s", git_HEAD);
-               return -3;
+               goto error_unlink_return;
        }
        if (adjust_shared_perm(git_HEAD)) {
-               unlink(lockpath);
                error("Unable to fix permissions on %s", lockpath);
-               return -4;
+       error_unlink_return:
+               unlink(lockpath);
+       error_free_return:
+               free(git_HEAD);
+               return -1;
        }
 
        done:
        if (logmsg && !read_ref(refs_heads_master, new_sha1))
                log_ref_write(ref_target, old_sha1, new_sha1, logmsg);
 
+       free(git_HEAD);
        return 0;
 }