[master] 740ee39c8 Detect the case where there is precisely zero bytes left in req->ws and return a 500 for that instead of panicing in VSB.

Poul-Henning Kamp phk at FreeBSD.org
Tue Mar 12 08:01:07 UTC 2019


commit 740ee39c8d6ffd36631a136cb9be23cdb13893d0
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Mar 12 08:00:05 2019 +0000

    Detect the case where there is precisely zero bytes left in req->ws
    and return a 500 for that instead of panicing in VSB.
    
    Fixes #2938

diff --git a/bin/varnishd/http2/cache_http2_deliver.c b/bin/varnishd/http2/cache_http2_deliver.c
index 20609e8e7..7ee71ac99 100644
--- a/bin/varnishd/http2/cache_http2_deliver.c
+++ b/bin/varnishd/http2/cache_http2_deliver.c
@@ -214,36 +214,28 @@ static const uint8_t h2_500_resp[] = {
 	0x1f, 0x27, 0x07, 'V', 'a', 'r', 'n', 'i', 's', 'h',
 };
 
-void v_matchproto_(vtr_deliver_f)
-h2_deliver(struct req *req, struct boc *boc, int sendbody)
+static int
+h2_build_headers(struct vsb *resp, struct req *req)
 {
-	ssize_t sz, sz1;
 	unsigned u, l;
-	uint8_t buf[6];
-	const char *r;
-	struct http *hp;
-	struct sess *sp;
-	struct h2_req *r2;
-	struct vsb resp;
 	int i;
+	struct http *hp;
+	const char *r;
 	const struct hpack_static *hps;
+	uint8_t buf[6];
+	ssize_t sz, sz1;
 
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-	CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
-	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
-	CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
-	sp = req->sp;
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-
-	VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
 	l = WS_Reserve(req->ws, 0);
-	AN(VSB_new(&resp, req->ws->f, l, VSB_FIXEDLEN));
+	if (l < 10)
+		return (-1);
+
+	AN(VSB_new(resp, req->ws->f, l, VSB_FIXEDLEN));
 
 	l = h2_status(buf, req->resp->status);
-	VSB_bcat(&resp, buf, l);
+	VSB_bcat(resp, buf, l);
 
 	hp = req->resp;
-	for (u = HTTP_HDR_FIRST; u < hp->nhd && !VSB_error(&resp); u++) {
+	for (u = HTTP_HDR_FIRST; u < hp->nhd && !VSB_error(resp); u++) {
 		r = strchr(hp->hd[u].b, ':');
 		AN(r);
 
@@ -264,25 +256,46 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
 			VSLb(req->vsl, SLT_Debug,
 			    "HP {%d, \"%s\", \"%s\"} <%s>",
 			    hps->idx, hps->name, hps->val, hp->hd[u].b);
-			h2_enc_len(&resp, 4, hps->idx, 0x10);
+			h2_enc_len(resp, 4, hps->idx, 0x10);
 		} else {
-			VSB_putc(&resp, 0x10);
+			VSB_putc(resp, 0x10);
 			sz--;
-			h2_enc_len(&resp, 7, sz, 0);
+			h2_enc_len(resp, 7, sz, 0);
 			for (sz1 = 0; sz1 < sz; sz1++)
-				VSB_putc(&resp, tolower(hp->hd[u].b[sz1]));
+				VSB_putc(resp, tolower(hp->hd[u].b[sz1]));
 
 		}
 
 		while (vct_islws(*++r))
 			continue;
 		sz = hp->hd[u].e - r;
-		h2_enc_len(&resp, 7, sz, 0);
-		VSB_bcat(&resp, r, sz);
+		h2_enc_len(resp, 7, sz, 0);
+		VSB_bcat(resp, r, sz);
 	}
-	if (VSB_finish(&resp)) {
-		WS_MarkOverflow(req->ws);
+	return (VSB_finish(resp));
+}
+
+void v_matchproto_(vtr_deliver_f)
+h2_deliver(struct req *req, struct boc *boc, int sendbody)
+{
+	ssize_t sz;
+	const char *r;
+	struct sess *sp;
+	struct h2_req *r2;
+	struct vsb resp;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
+	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
+	CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
+	sp = req->sp;
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+
+	VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
+
+	if (h2_build_headers(&resp, req)) {
 		// We ran out of workspace, return minimal 500
+		WS_MarkOverflow(req->ws);
 		VSLb(req->vsl, SLT_Error, "workspace_client overflow");
 		VSLb(req->vsl, SLT_RespStatus, "500");
 		VSLb(req->vsl, SLT_RespReason, "Internal Server Error");


More information about the varnish-commit mailing list