* [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test @ 2008-08-19 18:46 Jim Meyering 2008-08-20 19:40 ` Alex Riesen 2008-08-20 23:38 ` Brandon Casey 0 siblings, 2 replies; 8+ messages in thread From: Jim Meyering @ 2008-08-19 18:46 UTC (permalink / raw) To: git list We removed a handful of these useless if-before-free tests several months ago. This change removes a new one that snuck back in. Signed-off-by: Jim Meyering <meyering@redhat.com> --- There are four in regex.c, too, but that's imported code, so probably not worth modifying in git: compat/regex.c: if (var) free (var) compat/regex.c: if (preg->buffer != NULL) free (preg->buffer) compat/regex.c: if (preg->fastmap != NULL) free (preg->fastmap) compat/regex.c: if (preg->translate != NULL) free (preg->translate) remote.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/remote.c b/remote.c index f61a3ab..105668f 100644 --- a/remote.c +++ b/remote.c @@ -579,8 +579,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str) struct refspec *refspec; refspec = parse_refspec_internal(1, fetch_refspec, 1, 1); - if (refspec) - free(refspec); + free(refspec); return !!refspec; } -- 1.6.0.9.gae2e487 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-19 18:46 [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test Jim Meyering @ 2008-08-20 19:40 ` Alex Riesen 2008-08-20 20:22 ` Jim Meyering 2008-08-20 23:38 ` Brandon Casey 1 sibling, 1 reply; 8+ messages in thread From: Alex Riesen @ 2008-08-20 19:40 UTC (permalink / raw) To: Jim Meyering; +Cc: git list Jim Meyering, Tue, Aug 19, 2008 20:46:30 +0200: > We removed a handful of these useless if-before-free tests > several months ago. This change removes a new one that snuck back in. Something used to crash in free when passed NULL. It's one of the reasons why some cross-platform projects have xfree which does the check (sometimes depending on platform). Admittedly, it is a long time since I saw such a platform (some old SunOS it was, I believe). ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-20 19:40 ` Alex Riesen @ 2008-08-20 20:22 ` Jim Meyering 0 siblings, 0 replies; 8+ messages in thread From: Jim Meyering @ 2008-08-20 20:22 UTC (permalink / raw) To: Alex Riesen; +Cc: git list Alex Riesen <raa.lkml@gmail.com> wrote: > Jim Meyering, Tue, Aug 19, 2008 20:46:30 +0200: >> We removed a handful of these useless if-before-free tests >> several months ago. This change removes a new one that snuck back in. > > Something used to crash in free when passed NULL. It's one of the > reasons why some cross-platform projects have xfree which does the > check (sometimes depending on platform). Admittedly, it is a long time > since I saw such a platform (some old SunOS it was, I believe). Right. This was discussed at length back in February: http://thread.gmane.org/gmane.comp.version-control.git/74187 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-19 18:46 [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test Jim Meyering 2008-08-20 19:40 ` Alex Riesen @ 2008-08-20 23:38 ` Brandon Casey 2008-08-21 0:16 ` Junio C Hamano 1 sibling, 1 reply; 8+ messages in thread From: Brandon Casey @ 2008-08-20 23:38 UTC (permalink / raw) To: Jim Meyering; +Cc: Git Mailing List Jim Meyering wrote: > We removed a handful of these useless if-before-free tests > several months ago. This change removes a new one that snuck back in. > diff --git a/remote.c b/remote.c > index f61a3ab..105668f 100644 > --- a/remote.c > +++ b/remote.c > @@ -579,8 +579,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str) > struct refspec *refspec; > > refspec = parse_refspec_internal(1, fetch_refspec, 1, 1); > - if (refspec) > - free(refspec); > + free(refspec); > return !!refspec; > } Maybe we should also begin the process of not leaking memory here... diff --git a/remote.c b/remote.c index 7f2897b..984ad1b 100644 --- a/remote.c +++ b/remote.c @@ -449,6 +449,20 @@ static int verify_refname(char *name, int is_glob) return result; } +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 +581,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,8 +598,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str) struct refspec *refspec; refspec = parse_refspec_internal(1, fetch_refspec, 1, 1); - if (refspec) - free(refspec); + free_refspecs(refspec, 1); return !!refspec; } diff --git a/remote.h b/remote.h index 091b1d0..2601f6e 100644 --- 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); ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-20 23:38 ` Brandon Casey @ 2008-08-21 0:16 ` Junio C Hamano 2008-08-21 0:33 ` Brandon Casey 0 siblings, 1 reply; 8+ messages in thread From: Junio C Hamano @ 2008-08-21 0:16 UTC (permalink / raw) To: Brandon Casey; +Cc: Jim Meyering, Git Mailing List Brandon Casey <casey@nrlssc.navy.mil> writes: > Maybe we should also begin the process of not leaking memory here... > > diff --git a/remote.c b/remote.c > index 7f2897b..984ad1b 100644 > --- a/remote.c > +++ b/remote.c > @@ -449,6 +449,20 @@ static int verify_refname(char *name, int is_glob) > return result; > } > > +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); > +} Are you sure all the codepaths that stuff refspec[].{src,dst} give freeable pointer? E.g. if anybody splits a originally single string "refs/heads/foo:refs/remotes/origin/foo" into two by replacing the colon with NUL and pointing the halves, and/or such string came from argv[] without strdup(), I'd imagine free() would not like you very much. I didn't look, though. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-21 0:16 ` Junio C Hamano @ 2008-08-21 0:33 ` Brandon Casey 2008-08-21 2:42 ` Junio C Hamano 0 siblings, 1 reply; 8+ messages in thread From: Brandon Casey @ 2008-08-21 0:33 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jim Meyering, Git Mailing List Junio C Hamano wrote: > Brandon Casey <casey@nrlssc.navy.mil> writes: > >> Maybe we should also begin the process of not leaking memory here... >> >> diff --git a/remote.c b/remote.c >> index 7f2897b..984ad1b 100644 >> --- a/remote.c >> +++ b/remote.c >> @@ -449,6 +449,20 @@ static int verify_refname(char *name, int is_glob) >> return result; >> } >> >> +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); >> +} > > Are you sure all the codepaths that stuff refspec[].{src,dst} give > freeable pointer? remote.c:parse_refspec_internal() always does. This function is the producer of the refspec that is being passed to free_refspecs() in the two places where the patch called it. The code paths for each additionally use of free_refspecs would have to check that it is safe. Perhaps a comment is in order. If you don't think we're ready for free_refspecs we can still call free() manually in the two places I called free_refspecs. -brandon ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test 2008-08-21 0:33 ` Brandon Casey @ 2008-08-21 2:42 ` Junio C Hamano 2008-08-22 0:16 ` [PATCH] remote.c: add a function for deleting a refspec array and use it (twice) Brandon Casey 0 siblings, 1 reply; 8+ messages in thread From: Junio C Hamano @ 2008-08-21 2:42 UTC (permalink / raw) To: Brandon Casey; +Cc: Jim Meyering, Git Mailing List Brandon Casey <casey@nrlssc.navy.mil> writes: >> Are you sure all the codepaths that stuff refspec[].{src,dst} give >> freeable pointer? > > remote.c:parse_refspec_internal() always does. This function is the > producer of the refspec that is being passed to free_refspecs() in the two > places where the patch called it. > > The code paths for each additionally use of free_refspecs would have to > check that it is safe. Perhaps a comment is in order. > > If you don't think we're ready for free_refspecs we can still call free() > manually in the two places I called free_refspecs. Thanks. A generic helper like this is preferable, as long as (1) you made sure existing callsites are safe, and (2) the helper is clearly commented against misuse by future callsites. I personally do not think it would be a bad idea to even make a rule that refspec[].{src,dst} _must_ be freeable pointers. After all, we may have to deal with repositories with insane number of refs (not in millions but certainly in thousands), but it would be insane to have a remote with insane number of refspecs (even in hundreds). ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] remote.c: add a function for deleting a refspec array and use it (twice) 2008-08-21 2:42 ` Junio C Hamano @ 2008-08-22 0:16 ` Brandon Casey 0 siblings, 0 replies; 8+ messages in thread From: Brandon Casey @ 2008-08-22 0:16 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jim Meyering, Git Mailing List 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> --- remote.c | 29 +++++++++++++++++++++++++++-- remote.h | 1 + 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/remote.c b/remote.c index 105668f..3ef09a4 100644 --- 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; } diff --git a/remote.h b/remote.h index 091b1d0..2601f6e 100644 --- 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); -- 1.6.0.21.g35a2e ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-08-22 0:18 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-08-19 18:46 [PATCH] * remote.c (valid_fetch_refspec): remove useless if-before-free test Jim Meyering 2008-08-20 19:40 ` Alex Riesen 2008-08-20 20:22 ` Jim Meyering 2008-08-20 23:38 ` Brandon Casey 2008-08-21 0:16 ` Junio C Hamano 2008-08-21 0:33 ` Brandon Casey 2008-08-21 2:42 ` Junio C Hamano 2008-08-22 0:16 ` [PATCH] remote.c: add a function for deleting a refspec array and use it (twice) Brandon Casey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).