Skip to contentSkip to conversation

lib/hstor.c: avoid an unconditional leak in append_qparam

PATCH Applied Jim Meyering 3 participants 6 messages Sep 27, 2010 – Sep 28, 2010 Library code

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 lib/hstor.c: avoid an unconditional leak in append_qparam

---
I would have preferred to insert a single line right before the huri_field_escape call:

    char *v = strdup(val);

[would result in a more compact, single-hunk patch] but it looks like hail uses the anachronistic (pre-C99) "declare all vars at outer scope" style, so I conformed.

 lib/hstor.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
lib/hstor.c +4 -1
index 6c67bfa..79e0420 100644
@@ -676,6 +676,7 @@ static GString *append_qparam(GString *str, const char *key, const char *val,
 		       char *arg_char)
 {
 	char *stmp;
+	char *v;
 
 	str = g_string_append(str, arg_char);
 	arg_char[0] = '&';
@@ -683,9 +684,11 @@ static GString *append_qparam(GString *str, const char *key, const char *val,
 	str = g_string_append(str, key);
 	str = g_string_append(str, "=");
 
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
 	str = g_string_append(str, stmp);
 	free(stmp);
+	free(v);
 
 	return str;
 }

--
1.7.3.234.g7bba3

#1 lore raw

lib/hstor.c static GString *append_qparam(GString *str, const char *key, const char *val, · line 691

Quoted 6 lines · On Mon, 27 Sep 2010 10:53:06 +0200 Jim Meyering <[email protected]> wrote:
lib/hstor.c +3 -1
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
 	str = g_string_append(str, stmp);
 	free(stmp);
+	free(v);

I think you may be fooled by the ridiculous calling convention of huri_field_escape(). It takes a pointer to heap, then either returns its argument, or reallocates it, frees the argument, and returns the reallocated area. It frees with g_free, so it assumes its equivalence with free(), haha.

The end result, it either returns what strdup returned of frees it. Therefore if you free what strudup returned, you double-free it.

I honestly think this madness must stop and huri_field_escape must allocate a new buffer every time. Then we would not need the strdup there at all. It only exists to satisfy the requirement to pass a pointer to heap in case val is a const or whatnot.

-- Pete

#2 lore raw
Quoted 16 lines · Pete Zaitcev

lib/hstor.c static GString *append_qparam(GString *str, const char *key, const char *val, · line 691

Quoted 6 lines · On Mon, 27 Sep 2010 10:53:06 +0200 Jim Meyering <[email protected]> wrote:
lib/hstor.c +3 -1
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
 	str = g_string_append(str, stmp);
 	free(stmp);
+	free(v);

I think you may be fooled by the ridiculous calling convention of huri_field_escape(). It takes a pointer to heap, then either returns its argument, or reallocates it, frees the argument, and returns the reallocated area. It frees with g_free, so it assumes its equivalence with free(), haha.

Quoted 2 lines

The end result, it either returns what strdup returned of frees it. Therefore if you free what strudup returned, you double-free it.

Oh! You're right.
I missed the "g_free (signed_str);"
at the end of huri_field_escape.
Sorry about that.

Quoted 4 lines

I honestly think this madness must stop and huri_field_escape must allocate a new buffer every time. Then we would not need the strdup there at all. It only exists to satisfy the requirement to pass a pointer to heap in case val is a const or whatnot.

Making a function like huri_field_escape free a buffer allocated by the caller does seem to violate something fundamental.

#3 lore raw
In reply to Pete Zaitcev
Quoted 11 lines · Pete Zaitcev

lib/hstor.c static GString *append_qparam(GString *str, const char *key, const char *val, · line 691

Quoted 6 lines · On Mon, 27 Sep 2010 10:53:06 +0200 Jim Meyering<[email protected]> wrote:
lib/hstor.c +3 -1
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
  	str = g_string_append(str, stmp);
  	free(stmp);
+	free(v);

I think you may be fooled by the ridiculous calling convention

Doh, my memory and I were fooled, too.

Applied
#4 lore raw
In reply to Jim Meyering
Quoted 29 lines · Jim Meyering

---
I would have preferred to insert a single line right before the huri_field_escape call:

     char *v = strdup(val);

[would result in a more compact, single-hunk patch] but it looks like hail uses the anachronistic (pre-C99) "declare all vars at outer scope" style, so I conformed.

  lib/hstor.c |    5 ++++-
  1 files changed, 4 insertions(+), 1 deletions(-)
lib/hstor.c +1 -0
index 6c67bfa..79e0420 100644
@@ -676,6 +676,7 @@ static GString *append_qparam(GString *str, const char *key, const char *val,
  		       char *arg_char)
  {
  	char *stmp;
+	char *v;
 
  	str = g_string_append(str, arg_char);
  	arg_char[0] = '&';

lib/hstor.c static GString *append_qparam(GString *str, const char *key, const char *val, · line 692

Quoted 10 lines
lib/hstor.c +3 -1
@@ -683,9 +684,11 @@ static GString *append_qparam(GString *str, const char *key, const char *val,
  	str = g_string_append(str, key);
  	str = g_string_append(str, "=");
 
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
  	str = g_string_append(str, stmp);
  	free(stmp);
+	free(v);
 

applied

Yeah, I don't like C++ var decls; I think the code gets too disorganized, making it really easy to miss a decl when reviewing.

Jeff

#5 lore raw
Quoted 8 lines · On Mon, 27 Sep 2010 12:53:48 -0400 Jeff Garzik <[email protected]> wrote:

lib/hstor.c static GString *append_qparam(GString *str, const char *key, const char *val, · line 691

Quoted 6 lines
lib/hstor.c +3 -1
-	stmp = huri_field_escape(strdup(val), QUERY_ESCAPE_MASK);
+	v = strdup(val);
+	stmp = huri_field_escape(v, QUERY_ESCAPE_MASK);
  	str = g_string_append(str, stmp);
  	free(stmp);
+	free(v);

applied

I'm going to post a patch that undoes the damage. It's in testing.

-- Pete