[experimental-ims] 0679d60 Be much more cautious about how much workspace we have to build predictive vary string.
Poul-Henning Kamp
phk at FreeBSD.org
Thu Dec 18 10:27:43 CET 2014
commit 0679d603fe4dad3027206f0cb272cd9c4aedb557
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Apr 16 14:06:55 2012 +0000
Be much more cautious about how much workspace we have to build
predictive vary string.
Fixes #1120
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 073eb75..ee17d31 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -956,6 +956,7 @@ void RES_WriteObj(struct sess *sp);
struct vsb *VRY_Create(struct req *sp, const struct http *hp);
int VRY_Match(struct req *, const uint8_t *vary);
void VRY_Validate(const uint8_t *vary);
+void VRY_Prep(struct req *);
/* cache_vcl.c */
void VCL_Init(void);
diff --git a/bin/varnishd/cache/cache_center.c b/bin/varnishd/cache/cache_center.c
index 5530f1b..4a04f5b 100644
--- a/bin/varnishd/cache/cache_center.c
+++ b/bin/varnishd/cache/cache_center.c
@@ -1081,18 +1081,7 @@ cnt_lookup(struct sess *sp, struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
AZ(req->busyobj);
- if (req->hash_objhead == NULL) {
- /* Not a waiting list return */
- AZ(req->vary_b);
- AZ(req->vary_l);
- AZ(req->vary_e);
- (void)WS_Reserve(req->ws, 0);
- } else {
- AN(req->ws->r);
- }
- req->vary_b = (void*)req->ws->f;
- req->vary_e = (void*)req->ws->r;
- req->vary_b[2] = '\0';
+ VRY_Prep(req);
AZ(req->objcore);
oc = HSH_Lookup(sp);
@@ -1359,7 +1348,7 @@ cnt_restart(struct sess *sp, const struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-
+
req->director = NULL;
if (++req->restarts >= cache_param->max_restarts) {
req->err_code = 503;
diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c
index 138efda..bf6537f 100644
--- a/bin/varnishd/cache/cache_vary.c
+++ b/bin/varnishd/cache/cache_vary.c
@@ -176,22 +176,61 @@ vry_cmp(const uint8_t *v1, const uint8_t *v2)
return (retval);
}
+/**********************************************************************
+ * Prepare predictive vary string
+ */
+
+void
+VRY_Prep(struct req *req)
+{
+ if (req->hash_objhead == NULL) {
+ /* Not a waiting list return */
+ AZ(req->vary_b);
+ AZ(req->vary_l);
+ AZ(req->vary_e);
+ (void)WS_Reserve(req->ws, 0);
+ } else {
+ AN(req->ws->r);
+ }
+ req->vary_b = (void*)req->ws->f;
+ req->vary_e = (void*)req->ws->r;
+ if (req->vary_b + 2 < req->vary_e)
+ req->vary_b[2] = '\0';
+}
+
+/**********************************************************************
+ * Match vary strings, and build a new cached string if possible.
+ *
+ * Return zero if there is certainly no match.
+ * Return non-zero if there could be a match or if we couldn't tell.
+ */
+
int
VRY_Match(struct req *req, const uint8_t *vary)
{
uint8_t *vsp = req->vary_b;
char *h, *e;
unsigned lh, ln;
- int i, retval = 1, oflo = 0;
+ int i, oflo = 0;
AN(vsp);
while (vary[2]) {
+ if (vsp + 2 >= req->vary_e) {
+ /*
+ * Too little workspace to find out
+ */
+ oflo = 1;
+ break;
+ }
i = vry_cmp(vary, vsp);
if (i == 1) {
- /* Build a new entry */
+ /*
+ * Different header, build a new entry,
+ * then compare again with that new entry.
+ */
- i = http_GetHdr(req->http,
- (const char*)(vary+2), &h);
+ ln = 2 + vary[2] + 2;
+ i = http_GetHdr(req->http, (const char*)(vary+2), &h);
if (i) {
/* Trim trailing space */
e = strchr(h, '\0');
@@ -199,55 +238,55 @@ VRY_Match(struct req *req, const uint8_t *vary)
e--;
lh = e - h;
assert(lh < 0xffff);
+ ln += lh;
} else {
e = h = NULL;
lh = 0xffff;
}
- /* Length of the entire new vary entry */
- ln = 2 + vary[2] + 2 + (lh == 0xffff ? 0 : lh);
- if (vsp + ln >= req->vary_e) {
- vsp = req->vary_b;
+ if (vsp + ln + 2 >= req->vary_e) {
+ /*
+ * Not enough space to build new entry
+ * and put terminator behind it.
+ */
oflo = 1;
+ break;
}
- /*
- * We MUST have space for one entry and the end marker
- * after it, which prevents old junk from confusing us
- */
- assert(vsp + ln + 2 < req->vary_e);
-
vbe16enc(vsp, (uint16_t)lh);
memcpy(vsp + 2, vary + 2, vary[2] + 2);
- if (h != NULL && e != NULL) {
- memcpy(vsp + 2 + vsp[2] + 2, h, e - h);
- vsp[2 + vary[2] + 2 + (e - h) + 2] = '\0';
- } else
- vsp[2 + vary[2] + 2 + 2] = '\0';
+ if (h != NULL)
+ memcpy(vsp + 2 + vsp[2] + 2, h, lh);
+ vsp[ln + 0] = 0xff;
+ vsp[ln + 1] = 0xff;
+ vsp[ln + 2] = 0;
+ VRY_Validate(vsp);
+ req->vary_l = vsp + 3;
i = vry_cmp(vary, vsp);
- assert(i != 1); /* hdr must be the same now */
+ assert(i == 0 || i == 2);
+ }
+ if (i == 0) {
+ /* Same header, same contents*/
+ vsp += vry_len(vsp);
+ vary += vry_len(vary);
+ } else if (i == 2) {
+ /* Same header, different contents, cannot match */
+ return (0);
}
- if (i != 0)
- retval = 0;
- vsp += vry_len(vsp);
- vary += vry_len(vary);
}
- if (vsp + 3 > req->vary_e)
- oflo = 1;
-
if (oflo) {
- /* XXX: Should log this */
vsp = req->vary_b;
- }
- vsp[0] = 0xff;
- vsp[1] = 0xff;
- vsp[2] = 0;
- if (oflo)
req->vary_l = NULL;
- else
- req->vary_l = vsp + 3;
- return (retval);
+ if (vsp + 2 < req->vary_e) {
+ vsp[0] = 0xff;
+ vsp[1] = 0xff;
+ vsp[2] = 0;
+ }
+ return (0);
+ } else {
+ return (1);
+ }
}
void
diff --git a/bin/varnishtest/tests/r01120.vtc b/bin/varnishtest/tests/r01120.vtc
new file mode 100644
index 0000000..97bc2e5
--- /dev/null
+++ b/bin/varnishtest/tests/r01120.vtc
@@ -0,0 +1,24 @@
+varnishtest "insanely long vary string"
+
+server s1 {
+ rxreq
+ txresp -hdr "Vary: Foo" -body "xxxx"
+ rxreq
+ txresp -hdr "Vary: Foo" -body "yyyyy"
+} -start
+
+varnish v1 \
+ -cliok "param.set workspace_client 8k" \
+ -cliok "param.set workspace_backend 200k" \
+ -vcl+backend {
+} -start
+
+client c1 {
+ txreq -hdr "Foo: blabla"
+ rxresp
+ expect resp.bodylen == 4
+ #txreq -hdr "Foo: blablaA"
+ txreq -hdr "Foo: blablaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaaaaaaaaaaaaaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ rxresp
+ expect resp.bodylen == 5
+} -run
More information about the varnish-commit
mailing list