diff options
author | Junio C Hamano <junkio@cox.net> | 2007-01-26 17:49:00 -0800 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-01-28 02:16:46 -0800 |
commit | 47fc52e2876ed3a54cd4b77e0b0c4875fa3317b8 (patch) | |
tree | 48ed1a524b2a77a0608fc22147334717b3e18342 | |
parent | 8b5157e40718a2ee1d645c342d93df4e66335479 (diff) | |
download | git-47fc52e2876ed3a54cd4b77e0b0c4875fa3317b8.tar.gz git-47fc52e2876ed3a54cd4b77e0b0c4875fa3317b8.tar.xz |
create_symref(): do not assume pathname from git_path() persists long enough
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>
-rw-r--r-- | refs.c | 20 |
1 files changed, 11 insertions, 9 deletions
@@ -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; } |