[master] 91755a0 Return 500 if we cannot decode the stored object into the resp.* This can happen in a number of obscure corner-cases, which do not warrant a panic.

Poul-Henning Kamp phk at FreeBSD.org
Mon Nov 9 10:46:22 CET 2015


commit 91755a001a9691b3ce12c20ea1402164685c7ed9
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Nov 9 09:45:13 2015 +0000

    Return 500 if we cannot decode the stored object into the resp.*
    This can happen in a number of obscure corner-cases, which do not
    warrant a panic.
    
    Fixes:	#1807

diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 9080641..8e3fe0f 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -863,26 +863,30 @@ HTTP_Decode(struct http *to, const uint8_t *fm)
 {
 
 	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+	AN(to->vsl);
 	AN(fm);
-	if (vbe16dec(fm) > to->shd)
-		return(-1);
-	to->status = vbe16dec(fm + 2);
-	fm += 4;
-	for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
-		if (to->nhd == HTTP_HDR_METHOD || to->nhd == HTTP_HDR_URL) {
-			to->hd[to->nhd].b = NULL;
-			to->hd[to->nhd].e = NULL;
-			continue;
-		}
-		if (*fm == '\0')
-			return (0);
-		to->hd[to->nhd].b = (const void*)fm;
-		fm = (const void*)strchr((const void*)fm, '\0');
-		to->hd[to->nhd].e = (const void*)fm;
-		fm++;
-		if (to->vsl != NULL)
+	if (vbe16dec(fm) <= to->shd) {
+		to->status = vbe16dec(fm + 2);
+		fm += 4;
+		for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
+			if (to->nhd == HTTP_HDR_METHOD ||
+			    to->nhd == HTTP_HDR_URL) {
+				to->hd[to->nhd].b = NULL;
+				to->hd[to->nhd].e = NULL;
+				continue;
+			}
+			if (*fm == '\0')
+				return (0);
+			to->hd[to->nhd].b = (const void*)fm;
+			fm = (const void*)strchr((const void*)fm, '\0');
+			to->hd[to->nhd].e = (const void*)fm;
+			fm++;
 			http_VSLH(to, to->nhd);
+		}
 	}
+	VSLb(to->vsl, SLT_Error,
+	    "Too many headers to Decode object (%u vs. %u)",
+	    vbe16dec(fm), to->shd);
 	return (-1);
 }
 
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index b7afe84..da59078 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -129,8 +129,12 @@ cnt_deliver(struct worker *wrk, struct req *req)
 		EXP_Touch(req->objcore, req->t_prev);
 
 	HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
-	AZ(HTTP_Decode(req->resp,
-	    ObjGetattr(req->wrk, req->objcore, OA_HEADERS, NULL)));
+	if (HTTP_Decode(req->resp,
+	    ObjGetattr(req->wrk, req->objcore, OA_HEADERS, NULL))) {
+		req->err_code = 500;
+		req->req_step = R_STP_SYNTH;
+		return (REQ_FSM_MORE);
+	}
 	http_ForceField(req->resp, HTTP_HDR_PROTO, "HTTP/1.1");
 
 	if (req->is_hit)
@@ -493,9 +497,9 @@ cnt_miss(struct worker *wrk, struct req *req)
 	case VCL_RET_FETCH:
 		wrk->stats->cache_miss++;
 		VBF_Fetch(wrk, req, req->objcore, req->stale_oc, VBF_NORMAL);
-		req->req_step = R_STP_FETCH;
 		if (req->stale_oc != NULL)
 			(void)HSH_DerefObjCore(wrk, &req->stale_oc);
+		req->req_step = R_STP_FETCH;
 		return (REQ_FSM_MORE);
 	case VCL_RET_SYNTH:
 		req->req_step = R_STP_SYNTH;
diff --git a/bin/varnishtest/tests/r01807.vtc b/bin/varnishtest/tests/r01807.vtc
new file mode 100644
index 0000000..4696cd1
--- /dev/null
+++ b/bin/varnishtest/tests/r01807.vtc
@@ -0,0 +1,50 @@
+varnishtest "Decreasing http_max_hdr"
+
+server s1 {
+	rxreq
+	txresp \
+		-hdr "h00: 00" \
+		-hdr "h01: 01" \
+		-hdr "h02: 02" \
+		-hdr "h03: 03" \
+		-hdr "h04: 04" \
+		-hdr "h05: 05" \
+		-hdr "h06: 06" \
+		-hdr "h07: 07" \
+		-hdr "h08: 08" \
+		-hdr "h09: 09" \
+		-hdr "h10: 10" \
+		-hdr "h11: 11" \
+		-hdr "h12: 12" \
+		-hdr "h13: 13" \
+		-hdr "h14: 14" \
+		-hdr "h15: 15" \
+		-hdr "h16: 16" \
+		-hdr "h17: 17" \
+		-hdr "h18: 18" \
+		-hdr "h19: 19" \
+		-hdr "h20: 20" \
+		-hdr "h21: 21" \
+		-hdr "h22: 22" \
+		-hdr "h23: 23" \
+		-hdr "h24: 24"
+} -start
+
+varnish v1 -vcl+backend {
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 200
+	expect resp.http.h24 == 24
+} -run
+
+varnish v1 -cliok {param.set http_max_hdr 32}
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 500
+} -run
+



More information about the varnish-commit mailing list