[3.0] 424743b Fix varnishncsa memory leaks on duplicate headers

Martin Blix Grydeland martin at varnish-cache.org
Mon Nov 5 13:44:20 CET 2012


commit 424743bb37f498b42d905a5e4ff30e160e0ceaa4
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Wed Sep 12 15:26:20 2012 +0200

    Fix varnishncsa memory leaks on duplicate headers

diff --git a/bin/varnishncsa/varnishncsa.c b/bin/varnishncsa/varnishncsa.c
index ff07ed5..f66bb18 100644
--- a/bin/varnishncsa/varnishncsa.c
+++ b/bin/varnishncsa/varnishncsa.c
@@ -136,13 +136,18 @@ isprefix(const char *str, const char *prefix, const char *end,
 
 /*
  * Returns a copy of the first consecutive sequence of non-space
- * characters in the string.
+ * characters in the string in dst. dst will be free'd first if non-NULL.
  */
-static char *
-trimfield(const char *str, const char *end)
+static void
+trimfield(char **dst, const char *str, const char *end)
 {
 	size_t len;
-	char *p;
+
+	/* free if already set */
+	if (*dst != NULL) {
+		free(*dst);
+		*dst = NULL;
+	}
 
 	/* skip leading space */
 	while (str < end && *str && *str == ' ')
@@ -154,22 +159,26 @@ trimfield(const char *str, const char *end)
 			break;
 
 	/* copy and return */
-	p = malloc(len + 1);
-	assert(p != NULL);
-	memcpy(p, str, len);
-	p[len] = '\0';
-	return (p);
+	*dst = malloc(len + 1);
+	assert(*dst != NULL);
+	memcpy(*dst, str, len);
+	(*dst)[len] = '\0';
 }
 
 /*
  * Returns a copy of the entire string with leading and trailing spaces
- * trimmed.
+ * trimmed in dst. dst will be free'd first if non-NULL.
  */
-static char *
-trimline(const char *str, const char *end)
+static void
+trimline(char **dst, const char *str, const char *end)
 {
 	size_t len;
-	char *p;
+
+	/* free if already set */
+	if (*dst != NULL) {
+		free(*dst);
+		*dst = NULL;
+	}
 
 	/* skip leading space */
 	while (str < end && *str && *str == ' ')
@@ -184,11 +193,10 @@ trimline(const char *str, const char *end)
 		--len;
 
 	/* copy and return */
-	p = malloc(len + 1);
-	assert(p != NULL);
-	memcpy(p, str, len);
-	p[len] = '\0';
-	return (p);
+	*dst = malloc(len + 1);
+	assert(*dst != NULL);
+	memcpy(*dst, str, len);
+	(*dst)[len] = '\0';
 }
 
 static char *
@@ -284,9 +292,9 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 		}
 		lp->active = 1;
 		if (isprefix(ptr, "default", end, &next))
-			lp->df_h = trimfield(next, end);
+			trimfield(&lp->df_h, next, end);
 		else
-			lp->df_h = trimfield(ptr, end);
+			trimfield(&lp->df_h, ptr, end);
 		break;
 
 	case SLT_TxRequest:
@@ -296,7 +304,7 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_m = trimline(ptr, end);
+		trimline(&lp->df_m, ptr, end);
 		break;
 
 	case SLT_TxURL: {
@@ -310,10 +318,10 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 		}
 		qs = index(ptr, '?');
 		if (qs) {
-			lp->df_U = trimline(ptr, qs);
-			lp->df_q = trimline(qs, end);
+			trimline(&lp->df_U, ptr, qs);
+			trimline(&lp->df_q, qs, end);
 		} else {
-			lp->df_U = trimline(ptr, end);
+			trimline(&lp->df_U, ptr, end);
 		}
 		break;
 	}
@@ -325,7 +333,7 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_H = trimline(ptr, end);
+		trimline(&lp->df_H, ptr, end);
 		break;
 
 	case SLT_RxStatus:
@@ -335,14 +343,14 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_s = trimline(ptr, end);
+		trimline(&lp->df_s, ptr, end);
 		break;
 
 	case SLT_RxHeader:
 		if (!lp->active)
 			break;
 		if (isprefix(ptr, "content-length:", end, &next))
-			lp->df_b = trimline(next, end);
+			trimline(&lp->df_b, next, end);
 		else if (isprefix(ptr, "date:", end, &next) &&
 			 strptime(next, "%a, %d %b %Y %T", &lp->df_t) == NULL) {
 			clean_logline(lp);
@@ -357,16 +365,16 @@ collect_backend(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			break;
 		if (isprefix(ptr, "authorization:", end, &next) &&
 		    isprefix(next, "basic", end, &next)) {
-			lp->df_u = trimline(next, end);
+			trimline(&lp->df_u, next, end);
 		} else {
 			struct hdr *h;
 			size_t l;
-			h = malloc(sizeof(struct hdr));
+			h = calloc(1, sizeof(struct hdr));
 			AN(h);
 			AN(split);
 			l = strlen(split);
-			h->key = trimline(ptr, split-1);
-			h->value = trimline(split+1, split+l-1);
+			trimline(&h->key, ptr, split-1);
+			trimline(&h->value, split+1, split+l-1);
 			VTAILQ_INSERT_HEAD(&lp->req_headers, h, list);
 		}
 		break;
@@ -405,7 +413,7 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 		}
 		lp->active = 1;
-		lp->df_h = trimfield(ptr, end);
+		trimfield(&lp->df_h, ptr, end);
 		break;
 
 	case SLT_RxRequest:
@@ -415,7 +423,7 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_m = trimline(ptr, end);
+		trimline(&lp->df_m, ptr, end);
 		break;
 
 	case SLT_RxURL: {
@@ -429,10 +437,10 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 		}
 		qs = index(ptr, '?');
 		if (qs) {
-			lp->df_U = trimline(ptr, qs);
-			lp->df_q = trimline(qs, end);
+			trimline(&lp->df_U, ptr, qs);
+			trimline(&lp->df_q, qs, end);
 		} else {
-			lp->df_U = trimline(ptr, end);
+			trimline(&lp->df_U, ptr, end);
 		}
 		break;
 	}
@@ -444,7 +452,7 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_H = trimline(ptr, end);
+		trimline(&lp->df_H, ptr, end);
 		break;
 
 	case SLT_TxStatus:
@@ -453,7 +461,7 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 		if (lp->df_s != NULL)
 			clean_logline(lp);
 		else
-			lp->df_s = trimline(ptr, end);
+			trimline(&lp->df_s, ptr, end);
 		break;
 
 	case SLT_TxHeader:
@@ -466,15 +474,14 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 		if (tag == SLT_RxHeader &&
 		    isprefix(ptr, "authorization:", end, &next) &&
 		    isprefix(next, "basic", end, &next)) {
-			free(lp->df_u);
-			lp->df_u = trimline(next, end);
+			trimline(&lp->df_u, next, end);
 		} else {
 			struct hdr *h;
-			h = malloc(sizeof(struct hdr));
+			h = calloc(1, sizeof(struct hdr));
 			AN(h);
 			AN(split);
-			h->key = trimline(ptr, split);
-			h->value = trimline(split+1, end);
+			trimline(&h->key, ptr, split);
+			trimline(&h->value, split+1, end);
 			if (tag == SLT_RxHeader)
 				VTAILQ_INSERT_HEAD(&lp->req_headers, h, list);
 			else
@@ -491,12 +498,12 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			break;
 
 		struct hdr *h;
-		h = malloc(sizeof(struct hdr));
+		h = calloc(1, sizeof(struct hdr));
 		AN(h);
 		AN(split);
 
-		h->key = trimline(ptr, split);
-		h->value = trimline(split+1, end);
+		trimline(&h->key, ptr, split);
+		trimline(&h->value, split+1, end);
 
 		VTAILQ_INSERT_HEAD(&lp->vcl_log, h, list);
 		break;
@@ -528,7 +535,7 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
-		lp->df_b = trimline(ptr, end);
+		trimline(&lp->df_b, ptr, end);
 		break;
 
 	case SLT_SessionClose:
@@ -550,6 +557,8 @@ collect_client(struct logline *lp, enum VSL_tag_e tag, unsigned spec,
 			clean_logline(lp);
 			break;
 		}
+		if (lp->df_ttfb != NULL)
+			free(lp->df_ttfb);
 		lp->df_ttfb = strdup(ttfb);
 		t = l;
 		localtime_r(&t, &lp->df_t);



More information about the varnish-commit mailing list