Commit Diff


commit - 4f655d1bef17f1bc4ed551c53dd1b2d83c56b880
commit + d5c81d448ae4eec21053152e1c82c66eb11ca7a4
blob - 48165fc4dfb98dc55aa9bb49ceea9ff107e8fc26
blob + f571bc2b37e0f81d982871ec9029eb572253e75d
--- include/got_error.h
+++ include/got_error.h
@@ -147,6 +147,7 @@
 #define GOT_ERR_GIT_REPO_EXT	130
 #define GOT_ERR_CANNOT_PACK	131
 #define GOT_ERR_LONELY_PACKIDX	132
+#define GOT_ERR_OBJ_CSUM	133
 
 static const struct got_error {
 	int code;
@@ -301,6 +302,7 @@ static const struct got_error {
 	{ GOT_ERR_GIT_REPO_EXT, "unsupported repository format extension" },
 	{ GOT_ERR_CANNOT_PACK, "not enough objects to pack" },
 	{ GOT_ERR_LONELY_PACKIDX, "pack index has no corresponding pack file" },
+	{ GOT_ERR_OBJ_CSUM, "bad object checksum" },
 };
 
 /*
blob - ad8c052645bdb1fad1e36b8ca14e324f41bff53d
blob + 3833fedc8b779ac09969970c0ae89d5732c651cf
--- lib/got_lib_inflate.h
+++ lib/got_lib_inflate.h
@@ -20,6 +20,12 @@ struct got_inflate_checksum {
 
 	/* If not NULL, mix input bytes into this SHA1 context. */
 	SHA1_CTX *input_sha1;
+
+	/* If not NULL, mix output bytes into this CRC checksum. */
+	uint32_t *output_crc;
+
+	/* If not NULL, mix output bytes into this SHA1 context. */
+	SHA1_CTX *output_sha1;
 };
 
 struct got_inflate_buf {
blob - 7f91b3bcc5e247a002e805274461026d32267fe5
blob + f107a850167bfb93f97e10313c9351627cd8eb68
--- lib/got_lib_object.h
+++ lib/got_lib_object.h
@@ -103,7 +103,7 @@ const struct got_error *got_object_open_loose_fd(int *
 const struct got_error *got_object_open_packed(struct got_object **,
     struct got_object_id *, struct got_repository *);
 const struct got_error *got_object_read_header_privsep(struct got_object **,
-    struct got_repository *, int);
+    struct got_object_id *, struct got_repository *, int);
 const struct got_error *got_object_open(struct got_object **,
     struct got_repository *, struct got_object_id *);
 const struct got_error *got_object_raw_open(struct got_raw_object **,
blob - 852db60a614ec79d99a3416e34b5e0b018f27ed9
blob + 7592979912f4df4afc7d084b4a3779e769d66b04
--- lib/got_lib_object_parse.h
+++ lib/got_lib_object_parse.h
@@ -42,6 +42,7 @@ const struct got_error *got_read_file_to_mem(uint8_t *
 
 struct got_pack;
 struct got_packidx;
+struct got_inflate_checksum;
 
 const struct got_error *got_object_parse_header(struct got_object **, char *, size_t);
 const struct got_error *got_object_read_header(struct got_object **, int);
blob - dc1687fd0232a98260fd1d1f91425364de21521b
blob + e35958fa1bceef186dcfd71f9d4a132377b31766
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -369,6 +369,13 @@ struct got_imsg_pack {
 } __attribute__((__packed__));
 
 /*
+ * Structure for GOT_IMSG_OBJECT_REQUEST, GOT_IMSG_BLOB_REQUEST,
+ * GOT_IMSG_TREE_REQUEST, GOT_IMSG_COMMIT_REQUEST, and
+ * GOT_IMSG_TAG_REQUEST data.
+ */
+struct got_object_id;
+
+/*
  * Structure for GOT_IMSG_PACKED_OBJECT_REQUEST and
  * GOT_IMSG_PACKED_RAW_OBJECT_REQUEST data.
  */
@@ -428,8 +435,10 @@ const struct got_error *got_privsep_recv_imsg(struct i
 void got_privsep_send_error(struct imsgbuf *, const struct got_error *);
 const struct got_error *got_privsep_send_ack(struct imsgbuf *);
 const struct got_error *got_privsep_wait_ack(struct imsgbuf *);
-const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int);
-const struct got_error *got_privsep_send_raw_obj_req(struct imsgbuf *, int);
+const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int,
+    struct got_object_id *);
+const struct got_error *got_privsep_send_raw_obj_req(struct imsgbuf *, int,
+    struct got_object_id *);
 const struct got_error *got_privsep_send_raw_obj_outfd(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_commit_req(struct imsgbuf *, int,
     struct got_object_id *, int);
blob - aa993fb6f2b096a240a470976cbe73249014215a
blob + 5cb13a52c00956e749c0fce5abb67b88742b17b4
--- lib/inflate.c
+++ lib/inflate.c
@@ -93,6 +93,16 @@ csum_input(struct got_inflate_checksum *csum, const ch
 		SHA1Update(csum->input_sha1, buf, len);
 }
 
+static void
+csum_output(struct got_inflate_checksum *csum, const char *buf, size_t len)
+{
+	if (csum->output_crc)
+		*csum->output_crc = crc32(*csum->output_crc, buf, len);
+
+	if (csum->output_sha1)
+		SHA1Update(csum->output_sha1, buf, len);
+}
+
 const struct got_error *
 got_inflate_read(struct got_inflate_buf *zb, FILE *f, size_t *outlenp,
    size_t *consumed)
@@ -109,8 +119,8 @@ got_inflate_read(struct got_inflate_buf *zb, FILE *f, 
 	if (consumed)
 		*consumed = 0;
 	do {
-		char *csum_in = NULL;
-		size_t csum_avail = 0;
+		char *csum_in = NULL, *csum_out = NULL;
+		size_t csum_avail_in = 0, csum_avail_out = 0;
 
 		if (z->avail_in == 0) {
 			size_t n = fread(zb->inbuf, 1, zb->inlen, f);
@@ -126,11 +136,17 @@ got_inflate_read(struct got_inflate_buf *zb, FILE *f, 
 		}
 		if (zb->csum) {
 			csum_in = z->next_in;
-			csum_avail = z->avail_in;
+			csum_avail_in = z->avail_in;
+			csum_out = z->next_out;
+			csum_avail_out = z->avail_out;
 		}
 		ret = inflate(z, Z_SYNC_FLUSH);
-		if (zb->csum)
-			csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
+		if (zb->csum) {
+			csum_input(zb->csum, csum_in,
+			    csum_avail_in - z->avail_in);
+			csum_output(zb->csum, csum_out,
+			    csum_avail_out - z->avail_out);
+		}
 	} while (ret == Z_OK && z->avail_out > 0);
 
 	if (ret == Z_OK || ret == Z_BUF_ERROR) {
@@ -163,8 +179,8 @@ got_inflate_read_fd(struct got_inflate_buf *zb, int fd
 	if (consumed)
 		*consumed = 0;
 	do {
-		char *csum_in = NULL;
-		size_t csum_avail = 0;
+		char *csum_in = NULL, *csum_out = NULL;
+		size_t csum_avail_in = 0, csum_avail_out = 0;
 
 		if (z->avail_in == 0) {
 			ssize_t n = read(fd, zb->inbuf, zb->inlen);
@@ -180,11 +196,17 @@ got_inflate_read_fd(struct got_inflate_buf *zb, int fd
 		}
 		if (zb->csum) {
 			csum_in = z->next_in;
-			csum_avail = z->avail_in;
+			csum_avail_in = z->avail_in;
+			csum_out = z->next_out;
+			csum_avail_out = z->avail_out;
 		}
 		ret = inflate(z, Z_SYNC_FLUSH);
-		if (zb->csum)
-			csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
+		if (zb->csum) {
+			csum_input(zb->csum, csum_in,
+			    csum_avail_in - z->avail_in);
+			csum_output(zb->csum, csum_out,
+			    csum_avail_out - z->avail_out);
+		}
 	} while (ret == Z_OK && z->avail_out > 0);
 
 	if (ret == Z_OK || ret == Z_BUF_ERROR) {
@@ -216,8 +238,8 @@ got_inflate_read_mmap(struct got_inflate_buf *zb, uint
 	*consumed = 0;
 
 	do {
-		char *csum_in = NULL;
-		size_t csum_avail = 0;
+		char *csum_in = NULL, *csum_out = NULL;
+		size_t csum_avail_in = 0, csum_avail_out = 0;
 		size_t last_total_in = zb->z.total_in;
 
 		if (z->avail_in == 0) {
@@ -231,11 +253,17 @@ got_inflate_read_mmap(struct got_inflate_buf *zb, uint
 		}
 		if (zb->csum) {
 			csum_in = z->next_in;
-			csum_avail = z->avail_in;
+			csum_avail_in = z->avail_in;
+			csum_out = z->next_out;
+			csum_avail_out = z->avail_out;
 		}
 		ret = inflate(z, Z_SYNC_FLUSH);
-		if (zb->csum)
-			csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
+		if (zb->csum) {
+			csum_input(zb->csum, csum_in,
+			    csum_avail_in - z->avail_in);
+			csum_output(zb->csum, csum_out,
+			    csum_avail_out - z->avail_out);
+		}
 		*consumed += z->total_in - last_total_in;
 	} while (ret == Z_OK && z->avail_out > 0);
 
blob - bd60cd8b6abcd2895c9cbddca8e0c99886f92531
blob + 66e51456da85f0477bef25d1074a69d766e38fe2
--- lib/object.c
+++ lib/object.c
@@ -367,14 +367,15 @@ done:
 }
 
 static const struct got_error *
-request_object(struct got_object **obj, struct got_repository *repo, int fd)
+request_object(struct got_object **obj, struct got_object_id *id,
+    struct got_repository *repo, int fd)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].ibuf;
 
-	err = got_privsep_send_obj_req(ibuf, fd);
+	err = got_privsep_send_obj_req(ibuf, fd, id);
 	if (err)
 		return err;
 
@@ -383,7 +384,7 @@ request_object(struct got_object **obj, struct got_rep
 
 static const struct got_error *
 request_raw_object(uint8_t **outbuf, off_t *size, size_t *hdrlen, int outfd,
-    struct got_repository *repo, int infd)
+    struct got_object_id *id, struct got_repository *repo, int infd)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
@@ -395,7 +396,7 @@ request_raw_object(uint8_t **outbuf, off_t *size, size
 	if (outfd_child == -1)
 		return got_error_from_errno("dup");
 
-	err = got_privsep_send_raw_obj_req(ibuf, infd);
+	err = got_privsep_send_raw_obj_req(ibuf, infd, id);
 	if (err)
 		return err;
 
@@ -453,12 +454,12 @@ start_read_object_child(struct got_repository *repo)
 
 const struct got_error *
 got_object_read_header_privsep(struct got_object **obj,
-    struct got_repository *repo, int obj_fd)
+    struct got_object_id *id, struct got_repository *repo, int obj_fd)
 {
 	const struct got_error *err;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1)
-		return request_object(obj, repo, obj_fd);
+		return request_object(obj, id, repo, obj_fd);
 
 	err = start_read_object_child(repo);
 	if (err) {
@@ -466,24 +467,26 @@ got_object_read_header_privsep(struct got_object **obj
 		return err;
 	}
 
-	return request_object(obj, repo, obj_fd);
+	return request_object(obj, id, repo, obj_fd);
 }
 
 static const struct got_error *
 read_object_raw_privsep(uint8_t **outbuf, off_t *size, size_t *hdrlen,
-    int outfd, struct got_repository *repo, int obj_fd)
+    int outfd, struct got_object_id *id, struct got_repository *repo,
+    int obj_fd)
 {
 	const struct got_error *err;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1)
-		return request_raw_object(outbuf, size, hdrlen, outfd, repo,
-		    obj_fd);
+		return request_raw_object(outbuf, size, hdrlen, outfd, id,
+		    repo, obj_fd);
 
 	err = start_read_object_child(repo);
 	if (err)
 		return err;
 
-	return request_raw_object(outbuf, size, hdrlen, outfd, repo, obj_fd);
+	return request_raw_object(outbuf, size, hdrlen, outfd, id, repo,
+	    obj_fd);
 }
 
 const struct got_error *
@@ -514,7 +517,7 @@ got_object_open(struct got_object **obj, struct got_re
 		return err;
 	}
 
-	err = got_object_read_header_privsep(obj, repo, fd);
+	err = got_object_read_header_privsep(obj, id, repo, fd);
 	if (err)
 		return err;
 
@@ -568,7 +571,7 @@ got_object_raw_open(struct got_raw_object **obj, struc
 		if (err)
 			goto done;
 		err = read_object_raw_privsep(&outbuf, &size, &hdrlen, outfd,
-		    repo, fd);
+		    id, repo, fd);
 	}
 
 	*obj = calloc(1, sizeof(**obj));
@@ -745,14 +748,14 @@ read_packed_commit_privsep(struct got_commit_object **
 
 static const struct got_error *
 request_commit(struct got_commit_object **commit, struct got_repository *repo,
-    int fd)
+    int fd, struct got_object_id *id)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf;
 
-	err = got_privsep_send_commit_req(ibuf, fd, NULL, -1);
+	err = got_privsep_send_commit_req(ibuf, fd, id, -1);
 	if (err)
 		return err;
 
@@ -761,7 +764,7 @@ request_commit(struct got_commit_object **commit, stru
 
 static const struct got_error *
 read_commit_privsep(struct got_commit_object **commit, int obj_fd,
-    struct got_repository *repo)
+    struct got_object_id *id, struct got_repository *repo)
 {
 	const struct got_error *err;
 	int imsg_fds[2];
@@ -769,7 +772,7 @@ read_commit_privsep(struct got_commit_object **commit,
 	struct imsgbuf *ibuf;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].imsg_fd != -1)
-		return request_commit(commit, repo, obj_fd);
+		return request_commit(commit, repo, obj_fd, id);
 
 	ibuf = calloc(1, sizeof(*ibuf));
 	if (ibuf == NULL)
@@ -804,7 +807,7 @@ read_commit_privsep(struct got_commit_object **commit,
 	imsg_init(ibuf, imsg_fds[0]);
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf = ibuf;
 
-	return request_commit(commit, repo, obj_fd);
+	return request_commit(commit, repo, obj_fd, id);
 }
 
 
@@ -850,7 +853,7 @@ open_commit(struct got_commit_object **commit,
 		err = got_object_open_loose_fd(&fd, id, repo);
 		if (err)
 			return err;
-		err = read_commit_privsep(commit, fd, repo);
+		err = read_commit_privsep(commit, fd, id, repo);
 	}
 
 	if (err == NULL) {
@@ -959,14 +962,14 @@ read_packed_tree_privsep(struct got_tree_object **tree
 
 static const struct got_error *
 request_tree(struct got_tree_object **tree, struct got_repository *repo,
-    int fd)
+    int fd, struct got_object_id *id)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf;
 
-	err = got_privsep_send_tree_req(ibuf, fd, NULL, -1);
+	err = got_privsep_send_tree_req(ibuf, fd, id, -1);
 	if (err)
 		return err;
 
@@ -975,7 +978,7 @@ request_tree(struct got_tree_object **tree, struct got
 
 const struct got_error *
 read_tree_privsep(struct got_tree_object **tree, int obj_fd,
-    struct got_repository *repo)
+    struct got_object_id *id, struct got_repository *repo)
 {
 	const struct got_error *err;
 	int imsg_fds[2];
@@ -983,7 +986,7 @@ read_tree_privsep(struct got_tree_object **tree, int o
 	struct imsgbuf *ibuf;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].imsg_fd != -1)
-		return request_tree(tree, repo, obj_fd);
+		return request_tree(tree, repo, obj_fd, id);
 
 	ibuf = calloc(1, sizeof(*ibuf));
 	if (ibuf == NULL)
@@ -1019,7 +1022,7 @@ read_tree_privsep(struct got_tree_object **tree, int o
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf = ibuf;
 
 
-	return request_tree(tree, repo, obj_fd);
+	return request_tree(tree, repo, obj_fd, id);
 }
 
 static const struct got_error *
@@ -1064,7 +1067,7 @@ open_tree(struct got_tree_object **tree, struct got_re
 		err = got_object_open_loose_fd(&fd, id, repo);
 		if (err)
 			return err;
-		err = read_tree_privsep(tree, fd, repo);
+		err = read_tree_privsep(tree, fd, id, repo);
 	}
 
 	if (err == NULL) {
@@ -1301,7 +1304,7 @@ read_packed_blob_privsep(uint8_t **outbuf, size_t *siz
 
 static const struct got_error *
 request_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen, int outfd,
-    int infd, struct imsgbuf *ibuf)
+    int infd, struct got_object_id *id, struct imsgbuf *ibuf)
 {
 	const struct got_error *err = NULL;
 	int outfd_child;
@@ -1310,7 +1313,7 @@ request_blob(uint8_t **outbuf, size_t *size, size_t *h
 	if (outfd_child == -1)
 		return got_error_from_errno("dup");
 
-	err = got_privsep_send_blob_req(ibuf, infd, NULL, -1);
+	err = got_privsep_send_blob_req(ibuf, infd, id, -1);
 	if (err)
 		return err;
 
@@ -1330,7 +1333,7 @@ request_blob(uint8_t **outbuf, size_t *size, size_t *h
 
 static const struct got_error *
 read_blob_privsep(uint8_t **outbuf, size_t *size, size_t *hdrlen,
-    int outfd, int infd, struct got_repository *repo)
+    int outfd, int infd, struct got_object_id *id, struct got_repository *repo)
 {
 	const struct got_error *err;
 	int imsg_fds[2];
@@ -1339,7 +1342,8 @@ read_blob_privsep(uint8_t **outbuf, size_t *size, size
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].imsg_fd != -1) {
 		ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf;
-		return request_blob(outbuf, size, hdrlen, outfd, infd, ibuf);
+		return request_blob(outbuf, size, hdrlen, outfd, infd, id,
+		    ibuf);
 	}
 
 	ibuf = calloc(1, sizeof(*ibuf));
@@ -1375,7 +1379,7 @@ read_blob_privsep(uint8_t **outbuf, size_t *size, size
 	imsg_init(ibuf, imsg_fds[0]);
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf = ibuf;
 
-	return request_blob(outbuf, size, hdrlen, outfd, infd, ibuf);
+	return request_blob(outbuf, size, hdrlen, outfd, infd, id, ibuf);
 }
 
 static const struct got_error *
@@ -1430,7 +1434,7 @@ open_blob(struct got_blob_object **blob, struct got_re
 		if (err)
 			goto done;
 		err = read_blob_privsep(&outbuf, &size, &hdrlen, outfd, infd,
-		    repo);
+		    id, repo);
 	}
 	if (err)
 		goto done;
@@ -1674,14 +1678,14 @@ read_packed_tag_privsep(struct got_tag_object **tag,
 
 static const struct got_error *
 request_tag(struct got_tag_object **tag, struct got_repository *repo,
-    int fd)
+    int fd, struct got_object_id *id)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf;
 
-	err = got_privsep_send_tag_req(ibuf, fd, NULL, -1);
+	err = got_privsep_send_tag_req(ibuf, fd, id, -1);
 	if (err)
 		return err;
 
@@ -1690,7 +1694,7 @@ request_tag(struct got_tag_object **tag, struct got_re
 
 static const struct got_error *
 read_tag_privsep(struct got_tag_object **tag, int obj_fd,
-    struct got_repository *repo)
+    struct got_object_id *id, struct got_repository *repo)
 {
 	const struct got_error *err;
 	int imsg_fds[2];
@@ -1698,7 +1702,7 @@ read_tag_privsep(struct got_tag_object **tag, int obj_
 	struct imsgbuf *ibuf;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].imsg_fd != -1)
-		return request_tag(tag, repo, obj_fd);
+		return request_tag(tag, repo, obj_fd, id);
 
 	ibuf = calloc(1, sizeof(*ibuf));
 	if (ibuf == NULL)
@@ -1733,7 +1737,7 @@ read_tag_privsep(struct got_tag_object **tag, int obj_
 	imsg_init(ibuf, imsg_fds[0]);
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf = ibuf;
 
-	return request_tag(tag, repo, obj_fd);
+	return request_tag(tag, repo, obj_fd, id);
 }
 
 static const struct got_error *
@@ -1791,7 +1795,7 @@ open_tag(struct got_tag_object **tag, struct got_repos
 		err = got_object_open_loose_fd(&fd, id, repo);
 		if (err)
 			return err;
-		err = got_object_read_header_privsep(&obj, repo, fd);
+		err = got_object_read_header_privsep(&obj, id, repo, fd);
 		if (err)
 			return err;
 		obj_type = obj->type;
@@ -1802,7 +1806,7 @@ open_tag(struct got_tag_object **tag, struct got_repos
 		err = got_object_open_loose_fd(&fd, id, repo);
 		if (err)
 			return err;
-		err = read_tag_privsep(tag, fd, repo);
+		err = read_tag_privsep(tag, fd, id, repo);
 	}
 
 	if (err == NULL) {
blob - acb20d28e5fa0d935383503926b1be70789b9e42
blob + 9b4a7ee1895805282b36a747dfb244b5dd775ef8
--- lib/privsep.c
+++ lib/privsep.c
@@ -250,20 +250,22 @@ got_privsep_send_stop(int fd)
 }
 
 const struct got_error *
-got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd)
+got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd,
+    struct got_object_id *id)
 {
-	if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd, NULL, 0)
-	    == -1)
+	if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd,
+	    id, sizeof(*id)) == -1)
 		return got_error_from_errno("imsg_compose OBJECT_REQUEST");
 
 	return flush_imsg(ibuf);
 }
 
 const struct got_error *
-got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd)
+got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd,
+    struct got_object_id *id)
 {
-	if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd, NULL, 0)
-	    == -1)
+	if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd,
+	    id, sizeof(*id)) == -1)
 		return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST");
 
 	return flush_imsg(ibuf);
@@ -384,20 +386,21 @@ got_privsep_send_commit_req(struct imsgbuf *ibuf, int 
     struct got_object_id *id, int pack_idx)
 {
 	const struct got_error *err = NULL;
-	struct got_imsg_packed_object iobj, *iobjp;
+	struct got_imsg_packed_object iobj;
+	void *data;
 	size_t len;
 
-	if (id) { /* commit is packed */
+	if (pack_idx != -1) { /* commit is packed */
 		iobj.idx = pack_idx;
 		memcpy(iobj.id, id->sha1, sizeof(iobj.id));
-		iobjp = &iobj;
+		data = &iobj;
 		len = sizeof(iobj);
 	} else {
-		iobjp = NULL;
-		len = 0;
+		data = id;
+		len = sizeof(*id);
 	}
 
-	if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, iobjp, len)
+	if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, data, len)
 	    == -1) {
 		err = got_error_from_errno("imsg_compose COMMIT_REQUEST");
 		close(fd);
@@ -413,19 +416,24 @@ got_privsep_send_tree_req(struct imsgbuf *ibuf, int fd
 {
 	const struct got_error *err = NULL;
 	struct ibuf *wbuf;
-	size_t len = id ? sizeof(struct got_imsg_packed_object) : 0;
+	size_t len;
 
+	if (pack_idx != -1)
+		len = sizeof(struct got_imsg_packed_object);
+	else
+		len = sizeof(*id);
+
 	wbuf = imsg_create(ibuf, GOT_IMSG_TREE_REQUEST, 0, 0, len);
 	if (wbuf == NULL)
 		return got_error_from_errno("imsg_create TREE_REQUEST");
 
-	if (id) { /* tree is packed */
-		if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) {
-			err = got_error_from_errno("imsg_add TREE_ENTRY");
-			ibuf_free(wbuf);
-			return err;
-		}
+	if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) {
+		err = got_error_from_errno("imsg_add TREE_ENTRY");
+		ibuf_free(wbuf);
+		return err;
+	}
 
+	if (pack_idx != -1) { /* tree is packed */
 		if (imsg_add(wbuf, &pack_idx, sizeof(pack_idx)) == -1) {
 			err = got_error_from_errno("imsg_add TREE_ENTRY");
 			ibuf_free(wbuf);
@@ -443,20 +451,21 @@ const struct got_error *
 got_privsep_send_tag_req(struct imsgbuf *ibuf, int fd,
     struct got_object_id *id, int pack_idx)
 {
-	struct got_imsg_packed_object iobj, *iobjp;
+	struct got_imsg_packed_object iobj;
+	void *data;
 	size_t len;
 
-	if (id) { /* tag is packed */
+	if (pack_idx != -1) { /* tag is packed */
 		iobj.idx = pack_idx;
 		memcpy(iobj.id, id->sha1, sizeof(iobj.id));
-		iobjp = &iobj;
+		data = &iobj;
 		len = sizeof(iobj);
 	} else {
-		iobjp = NULL;
-		len = 0;
+		data = id;
+		len = sizeof(*id);
 	}
 
-	if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, iobjp, len)
+	if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, data, len)
 	    == -1)
 		return got_error_from_errno("imsg_compose TAG_REQUEST");
 
@@ -468,20 +477,21 @@ got_privsep_send_blob_req(struct imsgbuf *ibuf, int in
     struct got_object_id *id, int pack_idx)
 {
 	const struct got_error *err = NULL;
-	struct got_imsg_packed_object iobj, *iobjp;
+	struct got_imsg_packed_object iobj;
+	void *data;
 	size_t len;
 
-	if (id) { /* blob is packed */
+	if (pack_idx != -1) { /* blob is packed */
 		iobj.idx = pack_idx;
 		memcpy(iobj.id, id->sha1, sizeof(iobj.id));
-		iobjp = &iobj;
+		data = &iobj;
 		len = sizeof(iobj);
 	} else {
-		iobjp = NULL;
-		len = 0;
+		data = id;
+		len = sizeof(*id);
 	}
 
-	if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, iobjp, len)
+	if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, data, len)
 	    == -1) {
 		err = got_error_from_errno("imsg_compose BLOB_REQUEST");
 		close(infd);
blob - 42e4e1a923ac6b0970e0e49aaa75dcb4458deb0c
blob + f315741522c813f2f4e3d56e2caa15969cd6200d
--- lib/repository_admin.c
+++ lib/repository_admin.c
@@ -664,7 +664,8 @@ get_loose_object_ids(struct got_object_idset **loose_i
 				err = got_error_from_errno("fstat");
 				goto done;
 			}
-			err = got_object_read_header_privsep(&obj, repo, fd);
+			err = got_object_read_header_privsep(&obj, &id, repo,
+			    fd);
 			if (err)
 				goto done;
 			fd = -1; /* already closed */
blob - aac58b1e8c9fc029985629a172044af08fa045df
blob + 6ba4490d952e266de433edbadd35609faaeff1bf
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
@@ -186,6 +186,7 @@ read_packed_object(struct got_pack *pack, struct got_i
 	size_t mapoff = obj->off;
 	struct got_inflate_checksum csum;
 
+	memset(&csum, 0, sizeof(csum));
 	csum.input_sha1 = pack_sha1_ctx;
 	csum.input_crc = &obj->crc;
 
blob - 59f45b5cd15bd0d3e89af07aecad3d6cf6798541
blob + c5a389ba424f515e20c4b3afb8f183a6b2cdd9ae
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
@@ -38,6 +38,7 @@
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
+#include "got_lib_sha1.h"
 
 static volatile sig_atomic_t sigint_received;
 
@@ -73,7 +74,15 @@ main(int argc, char *argv[])
 		size_t size;
 		struct got_object *obj = NULL;
 		uint8_t *buf = NULL;
+		struct got_object_id id;
+		struct got_object_id expected_id;
+		struct got_inflate_checksum csum;
+		SHA1_CTX sha1_ctx;
 
+		SHA1Init(&sha1_ctx);
+		memset(&csum, 0, sizeof(csum));
+		csum.output_sha1 = &sha1_ctx;
+
 		memset(&imsg, 0, sizeof(imsg));
 		imsg.fd = -1;
 		memset(&imsg_outfd, 0, sizeof(imsg_outfd));
@@ -99,6 +108,13 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
+		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+		if (datalen != sizeof(expected_id)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			goto done;
+		}
+		memcpy(&expected_id, imsg.data, sizeof(expected_id));
+
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
@@ -146,14 +162,23 @@ main(int argc, char *argv[])
 
 		if (obj->size + obj->hdrlen <=
 		    GOT_PRIVSEP_INLINE_BLOB_DATA_MAX) {
-			err = got_inflate_to_mem(&buf, &size, NULL, NULL, f);
+			err = got_inflate_to_mem(&buf, &size, NULL, &csum, f);
 			if (err)
 				goto done;
 		} else {
-			err = got_inflate_to_fd(&size, f, NULL, imsg_outfd.fd);
+			err = got_inflate_to_fd(&size, f, &csum, imsg_outfd.fd);
 			if (err)
 				goto done;
 		}
+		SHA1Final(id.sha1, &sha1_ctx);
+		if (memcmp(expected_id.sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) {
+			char buf[SHA1_DIGEST_STRING_LENGTH];
+			err = got_error_fmt(GOT_ERR_OBJ_CSUM,
+			    "checksum failure for object %s",
+			    got_sha1_digest_to_str(expected_id.sha1, buf,
+			    sizeof(buf)));
+			goto done;
+		}
 
 		if (size < obj->hdrlen) {
 			err = got_error(GOT_ERR_BAD_OBJ_HDR);
blob - 93245b30e1136486de36bd3eb72dc2f86f739952
blob + 867dc5954e47c0673e815db7c0e25ae703e11658
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
@@ -38,6 +38,7 @@
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
+#include "got_lib_sha1.h"
 
 static volatile sig_atomic_t sigint_received;
 
@@ -48,23 +49,39 @@ catch_sigint(int signo)
 }
 
 static const struct got_error *
-read_commit_object(struct got_commit_object **commit, FILE *f)
+read_commit_object(struct got_commit_object **commit, FILE *f,
+    struct got_object_id *expected_id)
 {
-	struct got_object *obj;
+	struct got_object *obj = NULL;
 	const struct got_error *err = NULL;
 	size_t len;
 	uint8_t *p;
+	struct got_inflate_checksum csum;
+	SHA1_CTX sha1_ctx;
+	struct got_object_id id;
 
-	err = got_inflate_to_mem(&p, &len, NULL, NULL, f);
+	SHA1Init(&sha1_ctx);
+	memset(&csum, 0, sizeof(csum));
+	csum.output_sha1 = &sha1_ctx;
+
+	err = got_inflate_to_mem(&p, &len, NULL, &csum, f);
 	if (err)
 		return err;
 
-	err = got_object_parse_header(&obj, p, len);
-	if (err) {
-		free(p);
-		return err;
+	SHA1Final(id.sha1, &sha1_ctx);
+	if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) {
+		char buf[SHA1_DIGEST_STRING_LENGTH];
+		err = got_error_fmt(GOT_ERR_OBJ_CSUM,
+		    "checksum failure for object %s",
+		    got_sha1_digest_to_str(expected_id->sha1, buf,
+		    sizeof(buf)));
+		goto done;
 	}
 
+	err = got_object_parse_header(&obj, p, len);
+	if (err)
+		goto done;
+
 	if (len < obj->hdrlen + obj->size) {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
 		goto done;
@@ -80,7 +97,8 @@ read_commit_object(struct got_commit_object **commit, 
 	err = got_object_parse_commit(commit, p + obj->hdrlen, len);
 done:
 	free(p);
-	got_object_close(obj);
+	if (obj)
+		got_object_close(obj);
 	return err;
 }
 
@@ -89,6 +107,7 @@ main(int argc, char *argv[])
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf ibuf;
+	size_t datalen;
 
 	signal(SIGINT, catch_sigint);
 
@@ -107,6 +126,7 @@ main(int argc, char *argv[])
 		struct imsg imsg;
 		FILE *f = NULL;
 		struct got_commit_object *commit = NULL;
+		struct got_object_id expected_id;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -128,6 +148,13 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
+		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+		if (datalen != sizeof(expected_id)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			goto done;
+		}
+		memcpy(&expected_id, imsg.data, sizeof(expected_id));
+
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
@@ -140,7 +167,7 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_commit_object(&commit, f);
+		err = read_commit_object(&commit, f, &expected_id);
 		if (err)
 			goto done;
 
blob - d91d50bca13d75a6d38de4482f7e5605960b206c
blob + 4c0bf0f3e8dcb076c30c707c610ceca0aa0bdf80
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
@@ -38,6 +38,7 @@
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
+#include "got_lib_sha1.h"
 
 #ifndef nitems
 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
@@ -57,13 +58,22 @@ catch_sigint(int signo)
 }
 
 static const struct got_error *
-send_raw_obj(struct imsgbuf *ibuf, struct got_object *obj, int fd, int outfd)
+send_raw_obj(struct imsgbuf *ibuf, struct got_object *obj,
+    struct got_object_id *expected_id,
+    int fd, int outfd)
 {
 	const struct got_error *err = NULL;
 	uint8_t *data = NULL;
 	size_t len = 0, consumed;
 	FILE *f;
+	struct got_object_id id;
+	struct got_inflate_checksum csum;
+	SHA1_CTX sha1_ctx;
 
+	SHA1Init(&sha1_ctx);
+	memset(&csum, 0, sizeof(csum));
+	csum.output_sha1 = &sha1_ctx;
+
 	if (lseek(fd, SEEK_SET, 0) == -1) {
 		err = got_error_from_errno("lseek");
 		close(fd);
@@ -78,9 +88,9 @@ send_raw_obj(struct imsgbuf *ibuf, struct got_object *
 	}
 
 	if (obj->size + obj->hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX)
-		err = got_inflate_to_mem(&data, &len, &consumed, NULL, f);
+		err = got_inflate_to_mem(&data, &len, &consumed, &csum, f);
 	else
-		err = got_inflate_to_fd(&len, f, NULL, outfd);
+		err = got_inflate_to_fd(&len, f, &csum, outfd);
 	if (err)
 		goto done;
 
@@ -89,6 +99,17 @@ send_raw_obj(struct imsgbuf *ibuf, struct got_object *
 		goto done;
 	}
 
+	SHA1Final(id.sha1, &sha1_ctx);
+	if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) {
+		char buf[SHA1_DIGEST_STRING_LENGTH];
+		err = got_error_fmt(GOT_ERR_OBJ_CSUM,
+		    "checksum failure for object %s",
+		    got_sha1_digest_to_str(expected_id->sha1, buf,
+		    sizeof(buf)));
+		goto done;
+	}
+
+
 	err = got_privsep_send_raw_obj(ibuf, obj->size, obj->hdrlen, data);
 
 done:
@@ -107,6 +128,7 @@ main(int argc, char *argv[])
 	struct imsg imsg;
 	struct imsgbuf ibuf;
 	size_t datalen;
+	struct got_object_id expected_id;
 
 	signal(SIGINT, catch_sigint);
 
@@ -144,10 +166,11 @@ main(int argc, char *argv[])
 		}
 
 		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
-		if (datalen != 0) {
+		if (datalen != sizeof(expected_id)) {
 			err = got_error(GOT_ERR_PRIVSEP_LEN);
 			goto done;
 		}
+		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
@@ -160,6 +183,7 @@ main(int argc, char *argv[])
 
 		if (imsg.hdr.type == GOT_IMSG_RAW_OBJECT_REQUEST) {
 			struct imsg imsg_outfd;
+
 			err = got_privsep_recv_imsg(&imsg_outfd, &ibuf, 0);
 			if (err) {
 				if (imsg_outfd.hdr.len == 0)
@@ -189,7 +213,8 @@ main(int argc, char *argv[])
 				imsg_free(&imsg_outfd);
 				goto done;
 			}
-			err = send_raw_obj(&ibuf, obj, imsg.fd, imsg_outfd.fd);
+			err = send_raw_obj(&ibuf, obj, &expected_id,
+			    imsg.fd, imsg_outfd.fd);
 			imsg.fd = -1; /* imsg.fd is owned by send_raw_obj() */
 			if (close(imsg_outfd.fd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
blob - f3ce48de8619073672d23d6c63b6e2e5208861c6
blob + 54b081f2cd307441ac03be98dfdf41222edcf15c
--- libexec/got-read-tag/got-read-tag.c
+++ libexec/got-read-tag/got-read-tag.c
@@ -38,6 +38,7 @@
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
+#include "got_lib_sha1.h"
 
 static volatile sig_atomic_t sigint_received;
 
@@ -48,20 +49,38 @@ catch_sigint(int signo)
 }
 
 static const struct got_error *
-read_tag_object(struct got_tag_object **tag, FILE *f)
+read_tag_object(struct got_tag_object **tag, FILE *f,
+    struct got_object_id *expected_id)
 {
 	const struct got_error *err = NULL;
-	struct got_object *obj;
+	struct got_object *obj = NULL;
 	size_t len;
 	uint8_t *p;
+	struct got_inflate_checksum csum;
+	SHA1_CTX sha1_ctx;
+	struct got_object_id id;
 
-	err = got_inflate_to_mem(&p, &len, NULL, NULL, f);
+	SHA1Init(&sha1_ctx);
+	memset(&csum, 0, sizeof(csum));
+	csum.output_sha1 = &sha1_ctx;
+
+	err = got_inflate_to_mem(&p, &len, NULL, &csum, f);
 	if (err)
 		return err;
 
+	SHA1Final(id.sha1, &sha1_ctx);
+	if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) {
+		char buf[SHA1_DIGEST_STRING_LENGTH];
+		err = got_error_fmt(GOT_ERR_OBJ_CSUM,
+		    "checksum failure for object %s",
+		    got_sha1_digest_to_str(expected_id->sha1, buf,
+		    sizeof(buf)));
+		goto done;
+	}
+
 	err = got_object_parse_header(&obj, p, len);
 	if (err)
-		return err;
+		goto done;
 
 	if (len < obj->hdrlen + obj->size) {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
@@ -73,7 +92,8 @@ read_tag_object(struct got_tag_object **tag, FILE *f)
 	err = got_object_parse_tag(tag, p + obj->hdrlen, len);
 done:
 	free(p);
-	got_object_close(obj);
+	if (obj)
+		got_object_close(obj);
 	return err;
 }
 
@@ -82,6 +102,7 @@ main(int argc, char *argv[])
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf ibuf;
+	size_t datalen;
 
 	signal(SIGINT, catch_sigint);
 
@@ -100,6 +121,7 @@ main(int argc, char *argv[])
 		struct imsg imsg;
 		FILE *f = NULL;
 		struct got_tag_object *tag = NULL;
+		struct got_object_id expected_id;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -121,6 +143,13 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
+		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+		if (datalen != sizeof(expected_id)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			goto done;
+		}
+		memcpy(&expected_id, imsg.data, sizeof(expected_id));
+
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
@@ -133,7 +162,7 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_tag_object(&tag, f);
+		err = read_tag_object(&tag, f, &expected_id);
 		if (err)
 			goto done;
 
blob - aab6f584103a469db2e8b399113952f556555726
blob + 95e34c068c96ce1a4a00a1ea034531e243919dfd
--- libexec/got-read-tree/got-read-tree.c
+++ libexec/got-read-tree/got-read-tree.c
@@ -39,6 +39,7 @@
 #include "got_lib_object.h"
 #include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
+#include "got_lib_sha1.h"
 
 static volatile sig_atomic_t sigint_received;
 
@@ -50,19 +51,36 @@ catch_sigint(int signo)
 
 static const struct got_error *
 read_tree_object(struct got_pathlist_head *entries, int *nentries,
-    uint8_t **p, FILE *f)
+    uint8_t **p, FILE *f, struct got_object_id *expected_id)
 {
 	const struct got_error *err = NULL;
-	struct got_object *obj;
+	struct got_object *obj = NULL;
 	size_t len;
+	struct got_inflate_checksum csum;
+	SHA1_CTX sha1_ctx;
+	struct got_object_id id;
 
-	err = got_inflate_to_mem(p, &len, NULL, NULL, f);
+	SHA1Init(&sha1_ctx);
+	memset(&csum, 0, sizeof(csum));
+	csum.output_sha1 = &sha1_ctx;
+
+	err = got_inflate_to_mem(p, &len, NULL, &csum, f);
 	if (err)
 		return err;
 
+	SHA1Final(id.sha1, &sha1_ctx);
+	if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) {
+		char buf[SHA1_DIGEST_STRING_LENGTH];
+		err = got_error_fmt(GOT_ERR_OBJ_CSUM,
+		    "checksum failure for object %s",
+		    got_sha1_digest_to_str(expected_id->sha1, buf,
+		    sizeof(buf)));
+		goto done;
+	}
+
 	err = got_object_parse_header(&obj, *p, len);
 	if (err)
-		return err;
+		goto done;
 
 	if (len < obj->hdrlen + obj->size) {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
@@ -73,7 +91,8 @@ read_tree_object(struct got_pathlist_head *entries, in
 	len -= obj->hdrlen;
 	err = got_object_parse_tree(entries, nentries, *p + obj->hdrlen, len);
 done:
-	got_object_close(obj);
+	if (obj)
+		got_object_close(obj);
 	return err;
 }
 
@@ -82,6 +101,7 @@ main(int argc, char *argv[])
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf ibuf;
+	size_t datalen;
 
 	signal(SIGINT, catch_sigint);
 
@@ -102,6 +122,7 @@ main(int argc, char *argv[])
 		struct got_pathlist_head entries;
 		int nentries = 0;
 		uint8_t *buf = NULL;
+		struct got_object_id expected_id;
 
 		TAILQ_INIT(&entries);
 
@@ -125,6 +146,13 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
+		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+		if (datalen != sizeof(expected_id)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			goto done;
+		}
+		memcpy(&expected_id, imsg.data, sizeof(expected_id));
+
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
@@ -137,7 +165,8 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_tree_object(&entries, &nentries, &buf, f);
+		err = read_tree_object(&entries, &nentries, &buf, f,
+		    &expected_id);
 		if (err)
 			goto done;