git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).