[PATCH 2/3] create_symref(): do not assume pathname from git_path() persists long enough

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxx>
---
 * t7201-co.sh caught three failures.  The problem this patch is
   fixing overwrote and gave ".lock" in lockpath, then open() on
   that path failed and gave fd = -1 (because I scratched my
   head and re-run the test without cleaning, and O_EXCL
   triggered), which threw write_in_full() into infinite loop,
   which will be fixed with the next patch.

 refs.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/refs.c b/refs.c
index 5913185..4a52308 100644
--- 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;
 }
 
-- 
1.5.0.rc2.g8ac6-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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]