remote.c: add a function for deleting a refspec array and use it (twice)

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>
This commit is contained in:
Brandon Casey 2008-08-21 19:16:30 -05:00 коммит произвёл Junio C Hamano
Родитель a9da1663df
Коммит 2cb1f36d50
2 изменённых файлов: 28 добавлений и 2 удалений

Просмотреть файл

@ -449,6 +449,26 @@ static int verify_refname(char *name, int is_glob)
return result; 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) static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
{ {
int i; int i;
@ -567,7 +587,12 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
invalid: invalid:
if (verify) { 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; return NULL;
} }
die("Invalid refspec '%s'", refspec[i]); die("Invalid refspec '%s'", refspec[i]);
@ -579,7 +604,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str)
struct refspec *refspec; struct refspec *refspec;
refspec = parse_refspec_internal(1, fetch_refspec, 1, 1); refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
free(refspec); free_refspecs(refspec, 1);
return !!refspec; return !!refspec;
} }

Просмотреть файл

@ -78,6 +78,7 @@ void ref_remove_duplicates(struct ref *ref_map);
int valid_fetch_refspec(const char *refspec); int valid_fetch_refspec(const char *refspec);
struct refspec *parse_fetch_refspec(int nr_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); 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 match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
int nr_refspec, const char **refspec, int all); int nr_refspec, const char **refspec, int all);