git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Be more careful about updating refs

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Jan 15, 2008, 23:50 UTC
Message-ID
<alpine.LFD.1.00.0801151546560.2806@woody.linux-foundation.org>

This makes write_ref_sha1() more careful: it actually checks the SHA1 of the ref it is updating, and refuses to update a ref with an object that it cannot find.

Perhaps more importantly, it also refuses to update a branch head with a non-commit object. I don't quite know *how* the stable series maintainers were able to corrupt their repository to have a HEAD that pointed to a tag rather than a commit object, but they did. Which results in a totally broken repository that cannot be cloned or committed on.

So make it harder for people to shoot themselves in the foot like that.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---

I'm signing off on this, but I hope people will double-check this: I didn't actually test it very much.

 refs.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/refs.c b/refs.c
index 58f6d17..c3ffe03 100644
--- a/refs.c
+++ b/refs.c
@@ -1119,10 +1119,16 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
 	return 0;
 }
 
+static int is_branch(const char *refname)
+{
+	return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/");
+}
+
 int write_ref_sha1(struct ref_lock *lock,
 	const unsigned char *sha1, const char *logmsg)
 {
 	static char term = '\n';
+	struct object *o;
 
 	if (!lock)
 		return -1;
@@ -1130,6 +1136,19 @@ int write_ref_sha1(struct ref_lock *lock,
 		unlock_ref(lock);
 		return 0;
 	}
+	o = parse_object(sha1);
+	if (!o) {
+		error("Trying to write ref %s with nonexistant object %s",
+			lock->ref_name, sha1_to_hex(sha1));
+		unlock_ref(lock);
+		return -1;
+	}
+	if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
+		error("Trying to write non-commit object %s to branch %s",
+			sha1_to_hex(sha1), lock->ref_name);
+		unlock_ref(lock);
+		return -1;
+	}
 	if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
 	    write_in_full(lock->lock_fd, &term, 1) != 1
 		|| close(lock->lock_fd) < 0) {
Next: Linus Torvalds
Message 1 of 23 in “Be more careful about updating refs”
  1. Linus TorvaldsJan 15, 2008
  2. Linus TorvaldsJan 16, 2008
  3. Junio C HamanoJan 16, 2008
  4. Charles BaileyJan 17, 2008
  5. Johannes SixtJan 17, 2008
  6. Charles BaileyJan 17, 2008
  7. Johannes SixtJan 17, 2008
  8. Johannes SchindelinJan 17, 2008
  9. Charles BaileyJan 17, 2008
  10. Junio C HamanoJan 18, 2008
  11. Junio C HamanoJan 18, 2008
  12. Shawn O. PearceJan 18, 2008
  13. Junio C HamanoJan 18, 2008
  14. Shawn O. PearceJan 18, 2008
  15. Shawn O. PearceJan 18, 2008
  16. Shawn O. PearceJan 18, 2008
  17. Shawn O. PearceJan 18, 2008
  18. Shawn O. PearceJan 18, 2008
  19. Charles BaileyJan 17, 2008
  20. Junio C HamanoJan 16, 2008
  21. Linus TorvaldsJan 16, 2008
  22. Junio C HamanoJan 16, 2008
  23. Sam VilainJan 23, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.