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

Bug in fetch-pack.c, please confirm

From
Kyle J. McKay <mackyle@gmail.com>
Date
Mar 15, 2015, 06:37 UTC
Message-ID
<0758b2029b41448a77a4e4df1c4e406@74d39fa044aa309eaea14b9f57fe79c>
Hi guys,

So I was looking at fetch-pack.c (from master @ 52cae643, but I think it's the same everywhere):

# Lines 626-648
     for (retval = 1, ref = *refs; ref ; ref = ref->next) {
             const unsigned char *remote = ref->old_sha1;
             unsigned char local[20];
             struct object *o;
             o = lookup_object(remote);
             if (!o || !(o->flags & COMPLETE)) {
                     retval = 0;
                     if (!args->verbose)
                             continue;
                     fprintf(stderr,
                             "want %s (%s)\n", sha1_to_hex(remote),
                             ref->name);
                     continue;
             }
             hashcpy(ref->new_sha1, local);
             if (!args->verbose)
                     continue;
             fprintf(stderr,
                     "already have %s (%s)\n", sha1_to_hex(remote),
                     ref->name);
     }
Peff, weren't you having some issue with want and have and hide refs?
Tell me please how the "local" variable above gets initialized?

It's declared on the stack inside the for loop scope so only guaranteed to have garbage.

It's passed to hashcpy which has this prototype:
  inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src);
So it looks to me like garbage is copied into rev->new_sha1, yes?
Something's very wrong here.

It looks to me like the bug was introduced in 49bb805e (Do not ask for objects known to be complete. 2005-10-19).

I've taken a stab a a fix below.
-Kyle
-- 8< --
Subject: [PATCH] fetch-pack.c: do not use uninitialized sha1 value

Since 49bb805e (Do not ask for objects known to be complete. 2005-10-19) when the read_ref call was replaced with a parse_object call, the automatic variable 'local' containing an sha1 has been left uninitialized.

Subsequently in 1baaae5e (Make maximal use of the remote refs, 2005-10-28) the parse_object call was replaced with a lookup_object call but still the 'local' variable was left uninitialized.

However, it's used as the source to update another sha1 value in the case that we already have it and in that case the other ref will end up with whatever garbage was in the 'local' variable.

Fix this by removing the 'local' variable and using the value from the result of the lookup_object call instead.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
 fetch-pack.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fetch-pack.c b/fetch-pack.c
index 655ee642..c0b4d84f 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -621,29 +621,28 @@ static int everything_local(struct fetch_pack_args *args,
 		}
 	}
 
 	filter_refs(args, refs, sought, nr_sought);
 
 	for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 		const unsigned char *remote = ref->old_sha1;
-		unsigned char local[20];
 		struct object *o;
 
 		o = lookup_object(remote);
 		if (!o || !(o->flags & COMPLETE)) {
 			retval = 0;
 			if (!args->verbose)
 				continue;
 			fprintf(stderr,
 				"want %s (%s)\n", sha1_to_hex(remote),
 				ref->name);
 			continue;
 		}
 
-		hashcpy(ref->new_sha1, local);
+		hashcpy(ref->new_sha1, o->sha1);
 		if (!args->verbose)
 			continue;
 		fprintf(stderr,
 			"already have %s (%s)\n", sha1_to_hex(remote),
 			ref->name);
 	}
 	return retval;
---
Next: Junio C Hamano
Message 1 of 14 in “Bug in fetch-pack.c, please confirm”
  1. Kyle J. McKayMar 15, 2015
  2. Junio C HamanoMar 15, 2015
  3. Junio C HamanoMar 15, 2015
  4. Kyle J. McKayMar 15, 2015
  5. Jeff KingMar 16, 2015
  6. Junio C HamanoMar 19, 2015
  7. Jeff KingMar 19, 2015
  8. Junio C HamanoMar 19, 2015
  9. Jeff KingMar 19, 2015
  10. 1/4 filter_ref: avoid overwriting ref->old_sha1 with garbageJeff King, Mar 19, 2015
  11. Junio C HamanoMar 19, 2015
  12. 2/4 filter_ref: make a copy of extra "sought" entriesJeff King, Mar 19, 2015
  13. 3/4 fetch_refs_via_pack: free extra copy of refsJeff King, Mar 19, 2015
  14. 4/4 fetch-pack: remove dead assignment to ref->new_sha1Jeff King, Mar 19, 2015

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.