summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2013-03-17 04:22:36 -0400
committerJunio C Hamano <gitster@pobox.com>2013-03-17 12:49:03 -0700
commit75a95490474ab6e991cbbbd10d980498a9109648 (patch)
tree5acd800ccaad1c37aff8049fe4fb808314cbdaca
parent7e2010537e96d0a1144520222f20ba1dc3d61441 (diff)
downloadgit-75a95490474ab6e991cbbbd10d980498a9109648.tar.gz
avoid segfaults on parse_object failure
Many call-sites of parse_object assume that they will get a non-NULL return value; this is not the case if we encounter an error while parsing the object. This patch adds a wrapper function around parse_object that handles dying automatically, and uses it anywhere we immediately try to access the return value as a non-NULL pointer (i.e., anywhere that we would currently segfault). This wrapper may also be useful in other places. The most obvious one is code like: o = parse_object(sha1); if (!o) die(...); However, these should not be mechanically converted to parse_object_or_die, as the die message is sometimes customized. Later patches can address these sites on a case-by-case basis. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--bundle.c6
-rw-r--r--object.c10
-rw-r--r--object.h13
-rw-r--r--pack-refs.c2
4 files changed, 26 insertions, 5 deletions
diff --git a/bundle.c b/bundle.c
index 8d12816b9d..26ceebdb4b 100644
--- a/bundle.c
+++ b/bundle.c
@@ -279,12 +279,12 @@ int create_bundle(struct bundle_header *header, const char *path,
if (buf.len > 0 && buf.buf[0] == '-') {
write_or_die(bundle_fd, buf.buf, buf.len);
if (!get_sha1_hex(buf.buf + 1, sha1)) {
- struct object *object = parse_object(sha1);
+ struct object *object = parse_object_or_die(sha1, buf.buf);
object->flags |= UNINTERESTING;
add_pending_object(&revs, object, xstrdup(buf.buf));
}
} else if (!get_sha1_hex(buf.buf, sha1)) {
- struct object *object = parse_object(sha1);
+ struct object *object = parse_object_or_die(sha1, buf.buf);
object->flags |= SHOWN;
}
}
@@ -361,7 +361,7 @@ int create_bundle(struct bundle_header *header, const char *path,
* end up triggering "empty bundle"
* error.
*/
- obj = parse_object(sha1);
+ obj = parse_object_or_die(sha1, e->name);
obj->flags |= SHOWN;
add_pending_object(&revs, obj, e->name);
}
diff --git a/object.c b/object.c
index 4af3451bf8..20703f52ed 100644
--- a/object.c
+++ b/object.c
@@ -185,6 +185,16 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
return obj;
}
+struct object *parse_object_or_die(const unsigned char *sha1,
+ const char *name)
+{
+ struct object *o = parse_object(sha1);
+ if (o)
+ return o;
+
+ die(_("unable to parse object: %s"), name ? name : sha1_to_hex(sha1));
+}
+
struct object *parse_object(const unsigned char *sha1)
{
unsigned long size;
diff --git a/object.h b/object.h
index 6a97b6ba1a..97d384b80a 100644
--- a/object.h
+++ b/object.h
@@ -54,9 +54,20 @@ struct object *lookup_object(const unsigned char *sha1);
extern void *create_object(const unsigned char *sha1, int type, void *obj);
-/** Returns the object, having parsed it to find out what it is. **/
+/*
+ * Returns the object, having parsed it to find out what it is.
+ *
+ * Returns NULL if the object is missing or corrupt.
+ */
struct object *parse_object(const unsigned char *sha1);
+/*
+ * Like parse_object, but will die() instead of returning NULL. If the
+ * "name" parameter is not NULL, it is included in the error message
+ * (otherwise, the sha1 hex is given).
+ */
+struct object *parse_object_or_die(const unsigned char *sha1, const char *name);
+
/* Given the result of read_sha1_file(), returns the object after
* parsing it. eaten_p indicates if the object has a borrowed copy
* of buffer and the caller should not free() it.
diff --git a/pack-refs.c b/pack-refs.c
index f09a054228..6a689f35cb 100644
--- a/pack-refs.c
+++ b/pack-refs.c
@@ -40,7 +40,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
if (is_tag_ref) {
- struct object *o = parse_object(sha1);
+ struct object *o = parse_object_or_die(sha1, path);
if (o->type == OBJ_TAG) {
o = deref_tag(o, path, 0);
if (o)