Commit a14aa1e789aca48660466f37b2804b6a9d88e1c8

Carlos Martín Nieto 2014-03-04T20:09:17

pack-objects: free memory safely A few fixes have accumulated in this area which have made the freeing of data a bit muddy. Make sure to free the data only when needed and once. When we are going to write a delta to the packfile, we need to free the data, otherwise leave it. The current version of the code mixes up the checks for po->data and po->delta_data.

diff --git a/src/pack-objects.c b/src/pack-objects.c
index 8b65ac2..c881e6d 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -288,18 +288,21 @@ static int write_object(
 	git_odb_object *obj = NULL;
 	git_otype type;
 	unsigned char hdr[10], *zbuf = NULL;
-	void *delta_data = NULL;
-	void *data;
+	void *data = NULL;
 	size_t hdr_len, zbuf_len = COMPRESS_BUFLEN, data_len;
 	int error;
 
+	/*
+	 * If we have a delta base, let's use the delta to save space.
+	 * Otherwise load the whole object. 'data' ends up pointing to
+	 * whatever data we want to put into the packfile.
+	 */
 	if (po->delta) {
 		if (po->delta_data)
-			delta_data = po->delta_data;
-		else if ((error = get_delta(&delta_data, pb->odb, po)) < 0)
+			data = po->delta_data;
+		else if ((error = get_delta(&data, pb->odb, po)) < 0)
 				goto done;
 
-		data = delta_data;
 		data_len = po->delta_size;
 		type = GIT_OBJ_REF_DELTA;
 	} else {
@@ -346,13 +349,17 @@ static int write_object(
 
 			zbuf_len = COMPRESS_BUFLEN; /* reuse buffer */
 		}
-
-		if (po->delta)
-			git__free(delta_data);
 	}
 
-	if (po->delta_data) {
-		git__free(po->delta_data);
+	/*
+	 * If po->delta is true, data is a delta and it is our
+	 * responsibility to free it (otherwise it's a git_object's
+	 * data). We set po->delta_data to NULL in case we got the
+	 * data from there instead of get_delta(). If we didn't,
+	 * there's no harm.
+	 */
+	if (po->delta) {
+		git__free(data);
 		po->delta_data = NULL;
 	}