remote.c: add a function for deleting a refspec array and use it (twice)
authorBrandon Casey <casey@nrlssc.navy.mil>
Fri, 22 Aug 2008 00:16:30 +0000 (19:16 -0500)
committerJunio C Hamano <gitster@pobox.com>
Fri, 22 Aug 2008 07:15:37 +0000 (00:15 -0700)
A number of call sites allocate memory for a refspec array, populate
its members with heap memory, and then free only the refspec pointer
while leaking the memory allocated for the member elements. Provide
a function for freeing the elements of a refspec array and the array
itself.

Caution to callers: code paths must be checked to ensure that the
refspec members "src" and "dst" can be passed to free.

Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
remote.c
remote.h

index 105668f8a3cf13c2a759e9da4d0acc50ef781de9..3ef09a44a14622bb175d2a18bc46c946cde9a8a1 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -449,6 +449,26 @@ static int verify_refname(char *name, int is_glob)
        return result;
 }
 
+/*
+ * This function frees a refspec array.
+ * Warning: code paths should be checked to ensure that the src
+ *          and dst pointers are always freeable pointers as well
+ *          as the refspec pointer itself.
+ */
+void free_refspecs(struct refspec *refspec, int nr_refspec)
+{
+       int i;
+
+       if (!refspec)
+               return;
+
+       for (i = 0; i < nr_refspec; i++) {
+               free(refspec[i].src);
+               free(refspec[i].dst);
+       }
+       free(refspec);
+}
+
 static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
 {
        int i;
@@ -567,7 +587,12 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
 
  invalid:
        if (verify) {
-               free(rs);
+               /*
+                * nr_refspec must be greater than zero and i must be valid
+                * since it is only possible to reach this point from within
+                * the for loop above.
+                */
+               free_refspecs(rs, i+1);
                return NULL;
        }
        die("Invalid refspec '%s'", refspec[i]);
@@ -579,7 +604,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str)
        struct refspec *refspec;
 
        refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
-       free(refspec);
+       free_refspecs(refspec, 1);
        return !!refspec;
 }
 
index 091b1d041f8a4d255f59bfc001e098e692dbc15c..2601f6e76d52c6a201e3952fb8b2c988eed33700 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -78,6 +78,7 @@ void ref_remove_duplicates(struct ref *ref_map);
 int valid_fetch_refspec(const char *refspec);
 struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
 struct refspec *parse_push_refspec(int nr_refspec, const char **refspec);
+void free_refspecs(struct refspec *refspec, int nr_refspec);
 
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
               int nr_refspec, const char **refspec, int all);