[master] 0f3af407f Handle workspace allocation errors in VEP_Init()

Nils Goroll nils.goroll at uplex.de
Wed Apr 1 08:10:07 UTC 2020


commit 0f3af407f65ac4bc6d446c61fb3e3b50747194cd
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Wed Mar 18 16:57:15 2020 +0100

    Handle workspace allocation errors in VEP_Init()
    
    Turn assertion into VFP error
    
    The vtc is based upon r02645.vtc and reliably reproduces the panic
    without the patch by sweeping through possible amounts of free workspace
    ranging from 4 to 400 bytes.
    
    Fixes #3253

diff --git a/bin/varnishd/cache/cache_esi_fetch.c b/bin/varnishd/cache/cache_esi_fetch.c
index 74b430173..4592d37cc 100644
--- a/bin/varnishd/cache/cache_esi_fetch.c
+++ b/bin/varnishd/cache/cache_esi_fetch.c
@@ -165,8 +165,13 @@ vfp_esi_gzip_init(struct vfp_ctx *vc, struct vfp_entry *vfe)
 	if (vef == NULL)
 		return (VFP_ERROR);
 	vc->obj_flags |= OF_GZIPED | OF_CHGCE | OF_ESIPROC;
-	vef->vgz = VGZ_NewGzip(vc->wrk->vsl, "G F E");
 	vef->vep = VEP_Init(vc, vc->req, vfp_vep_callback, vef);
+	if (vef->vep == NULL) {
+		FREE_OBJ(vef);
+		return (VFP_ERROR);
+	}
+	vef->vgz = VGZ_NewGzip(vc->wrk->vsl, "G F E");
+
 	vef->ibuf_sz = cache_param->gzip_buffer;
 	vef->ibuf = calloc(1L, vef->ibuf_sz);
 	if (vef->ibuf == NULL)
@@ -232,6 +237,7 @@ static enum vfp_status v_matchproto_(vfp_init_f)
 vfp_esi_init(struct vfp_ctx *vc, struct vfp_entry *vfe)
 {
 	struct vef_priv *vef;
+	struct vep_state *vep;
 
 	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(vc->req, HTTP_MAGIC);
@@ -240,11 +246,14 @@ vfp_esi_init(struct vfp_ctx *vc, struct vfp_entry *vfe)
 		    "Attempted ESI on partial (206) response");
 		return (VFP_ERROR);
 	}
+	vep = VEP_Init(vc, vc->req, NULL, NULL);
+	if (vep == NULL)
+		return (VFP_ERROR);
 	ALLOC_OBJ(vef, VEF_MAGIC);
 	if (vef == NULL)
 		return (VFP_ERROR);
 	vc->obj_flags |= OF_ESIPROC;
-	vef->vep = VEP_Init(vc, vc->req, NULL, NULL);
+	vef->vep = vep;
 	vfe->priv1 = vef;
 	return (VFP_OK);
 }
diff --git a/bin/varnishd/cache/cache_esi_parse.c b/bin/varnishd/cache/cache_esi_parse.c
index 2cd1f85c8..995087aa5 100644
--- a/bin/varnishd/cache/cache_esi_parse.c
+++ b/bin/varnishd/cache/cache_esi_parse.c
@@ -1042,7 +1042,11 @@ VEP_Init(struct vfp_ctx *vc, const struct http *req, vep_callback_t *cb,
 	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(req, HTTP_MAGIC);
 	vep = WS_Alloc(vc->resp->ws, sizeof *vep);
-	AN(vep);
+	if (vep == NULL) {
+		VSLb(vc->wrk->vsl, SLT_VCL_Error,
+		     "VEP_Init() workspace overflow");
+		return (NULL);
+	}
 
 	INIT_OBJ(vep, VEP_MAGIC);
 	vep->url = req->hd[HTTP_HDR_URL].b;
diff --git a/bin/varnishtest/tests/r03253.vtc b/bin/varnishtest/tests/r03253.vtc
new file mode 100644
index 000000000..af72560c5
--- /dev/null
+++ b/bin/varnishtest/tests/r03253.vtc
@@ -0,0 +1,26 @@
+varnishtest "ESI: sweep through tight backend workspace conditions"
+
+server s1 -repeat 100 {
+	rxreq
+	txresp -gzipbody "<html>"
+} -start
+
+varnish v1 -vcl+backend {
+	import vtc;
+	import std;
+	sub vcl_recv {
+		return (pass);
+	}
+	sub vcl_backend_response {
+		vtc.workspace_alloc(backend, -4 *
+			(std.integer(bereq.xid, 1002) - 1000) / 2);
+		set beresp.do_esi = true;
+	}
+} -start
+
+client c1 -repeat 100 {
+	txreq -url "/"
+	# some responses will fail (503), some won't. All we care
+	# about here is the fact that we don't panic
+	rxresp
+} -run


More information about the varnish-commit mailing list