[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