[6.1] 2ce2abaa9 Return a canned minimal 500 if we run out of ws in H2-deliver.
hermunn
hermunn at varnish-software.com
Wed Oct 24 09:29:19 UTC 2018
commit 2ce2abaa96230418b03dce317c757c474b3b0177
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Oct 3 07:50:29 2018 +0000
Return a canned minimal 500 if we run out of ws in H2-deliver.
(Same as we do in H1)
Fixes #2589
diff --git a/bin/varnishd/http2/cache_http2_deliver.c b/bin/varnishd/http2/cache_http2_deliver.c
index 912eb88bc..8f4b56e1d 100644
--- a/bin/varnishd/http2/cache_http2_deliver.c
+++ b/bin/varnishd/http2/cache_http2_deliver.c
@@ -167,17 +167,35 @@ h2_enc_len(struct vsb *vsb, unsigned bits, unsigned val, uint8_t b0)
unsigned mask = (1U << bits) - 1U;
if (val >= mask) {
- AZ(VSB_putc(vsb, b0 | (uint8_t)mask));
+ VSB_putc(vsb, b0 | (uint8_t)mask);
val -= mask;
while (val >= 128) {
- AZ(VSB_putc(vsb, 0x80 | ((uint8_t)val & 0x7f)));
+ VSB_putc(vsb, 0x80 | ((uint8_t)val & 0x7f));
val >>= 7;
}
}
- AZ(VSB_putc(vsb, (uint8_t)val));
+ VSB_putc(vsb, (uint8_t)val);
return (0);
}
+/*
+ * Hand-crafted-H2-HEADERS-R-Us:
+ *
+ * This is a handbuilt HEADERS frame for when we run out of workspace
+ * during delivery.
+ */
+
+static const uint8_t h2_500_resp[] = {
+ // :status 500
+ 0x8e,
+
+ // content-length 0
+ 0x1f, 0x0d, 0x01, 0x30,
+
+ // server Varnish
+ 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)
{
@@ -203,10 +221,10 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
AN(VSB_new(&resp, req->ws->f, l, VSB_FIXEDLEN));
l = h2_status(buf, req->resp->status);
- AZ(VSB_bcat(&resp, buf, l));
+ VSB_bcat(&resp, buf, l);
hp = req->resp;
- for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+ for (u = HTTP_HDR_FIRST; u < hp->nhd && !VSB_error(&resp); u++) {
r = strchr(hp->hd[u].b, ':');
AN(r);
@@ -227,24 +245,32 @@ 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);
- AZ(h2_enc_len(&resp, 4, hps->idx, 0x10));
+ h2_enc_len(&resp, 4, hps->idx, 0x10);
} else {
- AZ(VSB_putc(&resp, 0x10));
+ VSB_putc(&resp, 0x10);
sz--;
- AZ(h2_enc_len(&resp, 7, sz, 0));
+ h2_enc_len(&resp, 7, sz, 0);
for (sz1 = 0; sz1 < sz; sz1++)
- AZ(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;
- AZ(h2_enc_len(&resp, 7, sz, 0));
- AZ(VSB_bcat(&resp, r, sz));
+ h2_enc_len(&resp, 7, sz, 0);
+ VSB_bcat(&resp, r, sz);
+ }
+ if (VSB_finish(&resp)) {
+ // We ran out of workspace, return minimal 500
+ // XXX: VSC counter ?
+ r = (const char*)h2_500_resp;
+ sz = sizeof h2_500_resp;
+ sendbody = 0;
+ } else {
+ sz = VSB_len(&resp);
+ r = req->ws->f;
}
- AZ(VSB_finish(&resp));
- sz = VSB_len(&resp);
AZ(req->wrk->v1l);
@@ -256,7 +282,7 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
H2_Send_Get(req->wrk, r2->h2sess, r2);
H2_Send(req->wrk, r2, H2_F_HEADERS,
(sendbody ? 0 : H2FF_HEADERS_END_STREAM) | H2FF_HEADERS_END_HEADERS,
- sz, req->ws->f);
+ sz, r);
H2_Send_Rel(r2->h2sess, r2);
req->acct.resp_hdrbytes += sz;
diff --git a/bin/varnishtest/tests/r02589.vtc b/bin/varnishtest/tests/r02589.vtc
new file mode 100644
index 000000000..418cc6833
--- /dev/null
+++ b/bin/varnishtest/tests/r02589.vtc
@@ -0,0 +1,29 @@
+varnishtest "workspace overrun on h/2 delivery"
+
+server s1 {
+ rxreq
+ txresp -hdrlen Foo 500
+} -start
+
+varnish v1 -vcl+backend {
+ import vtc;
+ sub vcl_deliver {
+ vtc.workspace_alloc(client, -50);
+ }
+} -start
+
+varnish v1 -cliok "param.set feature +http2"
+varnish v1 -cliok "param.set debug +syncvsl"
+varnish v1 -cliok "param.set vsl_mask +H2TxHdr"
+varnish v1 -cliok "param.set vsl_mask +H2TxBody"
+
+
+client c1 {
+ stream 1 {
+ txreq
+ rxresp
+ expect resp.status == 500
+ expect resp.http.content-length == 0
+ expect resp.http.server == "Varnish"
+ } -run
+} -run
More information about the varnish-commit
mailing list