summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-03-04 20:09:17 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2014-03-04 20:11:50 +0100
commita14aa1e789aca48660466f37b2804b6a9d88e1c8 (patch)
tree8452ecf3547d2839ae115ef29068022c322ff9e2
parentbb3687c5a8180c39d12b437ca1822ac43482b26f (diff)
downloadlibgit2-a14aa1e789aca48660466f37b2804b6a9d88e1c8.tar.gz
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.
-rw-r--r--src/pack-objects.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 8b65ac26a..c881e6d99 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;
}