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

[PATCH] sha1_loose_object_info: handle errors from unpack_sha1_rest

From
Jeff King <peff@peff.net>
Date
Oct 5, 2017, 05:59 UTC
Message-ID
<20171005055952.t5ef7hyolyevoj3d@sigill.intra.peff.net>

When a caller of sha1_object_info_extended() sets the "contentp" field in object_info, we call unpack_sha1_rest() but do not check whether it signaled an error.

This causes two problems:
  1. We pass back NULL to the caller via the contentp field,
     but the function returns "0" for success. A caller
     might reasonably expect after a successful return that
     it can access contentp without a NULL check and
     segfault.
     As it happens, this is impossible to trigger in the
     current code. There is exactly one caller which uses
     contentp, read_object(). And the only thing it does
     after a successful call is to return the content
     pointer to its caller, using NULL as a sentinel for
     errors. So in effect it converts the success code from
     sha1_object_info_extended() back into an error!
     But this is still worth addressing avoid problems for
     future users of "contentp".
  2. Callers of unpack_sha1_rest() are expected to close the
     zlib stream themselves on error. Which means that we're
     leaking the stream.

The problem in (1) comes from from c84a1f3ed4 (sha1_file: refactor read_object, 2017-06-21), which added the contentp field. Before that, we called unpack_sha1_rest() via unpack_sha1_file(), which directly used the NULL to signal an error.

But note that the leak in (2) is actually older than that. The original unpack_sha1_file() directly returned the result of unpack_sha1_rest() to its caller, when it should have been closing the zlib stream itself on error.

Signed-off-by: Jeff King <peff@peff.net>
---
 sha1_file.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sha1_file.c b/sha1_file.c
index 09ad64ce55..10c3a0083d 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1124,10 +1124,14 @@ static int sha1_loose_object_info(const unsigned char *sha1,
 	} else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
 		status = error("unable to parse %s header", sha1_to_hex(sha1));
 
-	if (status >= 0 && oi->contentp)
+	if (status >= 0 && oi->contentp) {
 		*oi->contentp = unpack_sha1_rest(&stream, hdr,
 						 *oi->sizep, sha1);
-	else
+		if (!*oi->contentp) {
+			git_inflate_end(&stream);
+			status = -1;
+		}
+	} else
 		git_inflate_end(&stream);
 
 	munmap(map, mapsize);
-- 
2.14.2.1117.g65a3442612
Next: Junio C Hamano
Message 1 of 5 in “sha1_loose_object_info: handle errors from unpack_sha1_rest”
  1. sha1_loose_object_info: handle errors from unpack_sha1_restJeff King, Oct 5, 2017
  2. Junio C HamanoOct 6, 2017
  3. Jeff KingOct 6, 2017
  4. Jeff KingOct 6, 2017
  5. Junio C HamanoOct 10, 2017

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.