The busyobj->h_content_length is a pointer to the header on the
workspace of the fetch initiating worker. This is not safe when doing
streaming.

This patch removes busyobj->h_content_length and replaces it with a
flag and an attribute instead.
---
 bin/varnishd/cache/cache.h          |    4 +++-
 bin/varnishd/cache/cache_center.c   |    3 +--
 bin/varnishd/cache/cache_fetch.c    |    9 +++++----
 bin/varnishd/cache/cache_response.c |    5 +++--
 bin/varnishd/cache/cache_rfc2616.c  |    5 +++--
 5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 4f260e9..0bc3f59 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -523,7 +523,8 @@ struct busyobj {
        struct vef_priv         *vef_priv;
 
        unsigned                should_close;
-       char                    *h_content_length;
+       unsigned                has_content_length;
+       ssize_t                 content_length;
 
        unsigned                do_esi;
        unsigned                do_gzip;
@@ -768,6 +769,7 @@ int EXP_Touch(struct objcore *oc);
 int EXP_NukeOne(struct worker *w, struct lru *lru);
 
 /* cache_fetch.c */
+ssize_t FetchNumber(const char *nbr, int radix);
 struct storage *FetchStorage(struct worker *w, ssize_t sz);
 int FetchError(struct worker *w, const char *error);
 int FetchError2(struct worker *w, const char *error, const char *more);
diff --git a/bin/varnishd/cache/cache_center.c 
b/bin/varnishd/cache/cache_center.c
index 2909212..f074c4b 100644
--- a/bin/varnishd/cache/cache_center.c
+++ b/bin/varnishd/cache/cache_center.c
@@ -233,8 +233,7 @@ cnt_prepresp(struct sess *sp, struct worker *wrk, struct 
req *req)
                wrk->res_mode |= RES_LEN;
 
        if (wrk->busyobj != NULL &&
-           (wrk->busyobj->h_content_length != NULL ||
-           !wrk->busyobj->do_stream) &&
+           (wrk->busyobj->has_content_length || !wrk->busyobj->do_stream) &&
            !wrk->busyobj->do_gzip && !wrk->busyobj->do_gunzip)
                wrk->res_mode |= RES_LEN;
 
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 8cf9350..b9e7ef0 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -205,8 +205,8 @@ FetchStorage(struct worker *wrk, ssize_t sz)
  * Convert a string to a size_t safely
  */
 
-static ssize_t
-fetch_number(const char *nbr, int radix)
+ssize_t
+FetchNumber(const char *nbr, int radix)
 {
        uintmax_t cll;
        ssize_t cl;
@@ -291,7 +291,7 @@ fetch_chunked(struct worker *wrk, struct http_conn *htc)
                        return (FetchError(wrk,"chunked header no NL"));
 
                buf[u] = '\0';
-               cl = fetch_number(buf, 16);
+               cl = FetchNumber(buf, 16);
                if (cl < 0)
                        return (FetchError(wrk,"chunked header number syntax"));
 
@@ -527,7 +527,8 @@ FetchBody(struct worker *wrk, struct busyobj *bo)
                mklen = 1;
                break;
        case BS_LENGTH:
-               cl = fetch_number(bo->h_content_length, 10);
+               AN(bo->has_content_length);
+               cl = bo->content_length;
                bo->vfp->begin(wrk, cl > 0 ? cl : 0);
                cls = fetch_straight(wrk, htc, cl);
                mklen = 1;
diff --git a/bin/varnishd/cache/cache_response.c 
b/bin/varnishd/cache/cache_response.c
index 5724f07..86f4517 100644
--- a/bin/varnishd/cache/cache_response.c
+++ b/bin/varnishd/cache/cache_response.c
@@ -353,9 +353,10 @@ RES_StreamStart(struct sess *sp)
                http_Unset(sp->req->resp, H_Content_Encoding);
 
        if (!(sp->wrk->res_mode & RES_CHUNKED) &&
-           sp->wrk->busyobj->h_content_length != NULL)
+           sp->wrk->busyobj->has_content_length &&
+           !http_GetHdr(sp->req->resp, H_Content_Length, NULL))
                http_PrintfHeader(sp->wrk, sp->vsl_id, sp->req->resp,
-                   "Content-Length: %s", sp->wrk->busyobj->h_content_length);
+                   "Content-Length: %zd", sp->wrk->busyobj->content_length);
 
        sp->wrk->acct_tmp.hdrbytes +=
            http_Write(sp->wrk, sp->vsl_id, sp->req->resp, 1);
diff --git a/bin/varnishd/cache/cache_rfc2616.c 
b/bin/varnishd/cache/cache_rfc2616.c
index 1b67d81..59d4e2c 100644
--- a/bin/varnishd/cache/cache_rfc2616.c
+++ b/bin/varnishd/cache/cache_rfc2616.c
@@ -239,8 +239,9 @@ RFC2616_Body(const struct sess *sp)
                return (BS_ERROR);
        }
 
-       if (http_GetHdr(hp, H_Content_Length,
-           &sp->wrk->busyobj->h_content_length)) {
+       if (http_GetHdr(hp, H_Content_Length, &b)) {
+               sp->wrk->busyobj->has_content_length = 1;
+               sp->wrk->busyobj->content_length = FetchNumber(b, 10);
                sp->wrk->stats.fetch_length++;
                return (BS_LENGTH);
        }
-- 
1.7.4.1


_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to