[master] 2f8e02a3d Check VCL_HEADER vmod arguments
Nils Goroll
nils.goroll at uplex.de
Wed Jun 2 16:56:04 UTC 2021
commit 2f8e02a3d52d47864ba8bd453f7b7182c0e20472
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Wed Jun 2 18:23:59 2021 +0200
Check VCL_HEADER vmod arguments
When a VCL_HEADER argument is a vmod return value, it could be
- NULL for an error condition
- from a different context
Also, we should not assert on HDR_OBJ in VRT_selecthttp() to
facilitate error handling in vmods.
Fixes #3623
diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index d6f982b1d..1289c1ac2 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -257,6 +257,9 @@ VRT_selecthttp(VRT_CTX, enum gethdr_e where)
case HDR_RESP:
hp = ctx->http_resp;
break;
+ case HDR_OBJ:
+ hp = NULL;
+ break;
default:
WRONG("VRT_selecthttp 'where' invalid");
}
diff --git a/bin/varnishtest/tests/m00006.vtc b/bin/varnishtest/tests/m00006.vtc
index 24ad5f934..1004277c5 100644
--- a/bin/varnishtest/tests/m00006.vtc
+++ b/bin/varnishtest/tests/m00006.vtc
@@ -13,6 +13,15 @@ varnish v1 -vcl+backend {
sub vcl_recv {
std.collect(req.http.foo);
}
+ sub vcl_hash {
+ hash_data("/");
+ return (lookup);
+ }
+ sub vcl_hit {
+ if (req.url == "/obj") {
+ std.collect(obj.http.foo);
+ }
+ }
sub vcl_backend_fetch {
std.collect(bereq.http.baz);
}
@@ -29,4 +38,7 @@ client c1 {
rxresp
expect resp.http.bar == "a, b"
expect resp.http.qux == "c; d"
+ txreq -url "/obj"
+ rxresp
+ expect resp.status == 503
} -run
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index fa75dd130..f75016da0 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -789,26 +789,34 @@ xyzzy_collect(VRT_CTX, VCL_STRANDS s)
/* cf. VRT_SetHdr() */
VCL_VOID
-xyzzy_sethdr(VRT_CTX, VCL_HEADER hs, VCL_STRANDS s)
+xyzzy_sethdr(VRT_CTX, VCL_HEADER hdr, VCL_STRANDS s)
{
struct http *hp;
const char *b;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
- AN(hs);
- AN(hs->what);
- hp = VRT_selecthttp(ctx, hs->where);
+ if (hdr == NULL) {
+ VRT_fail(ctx, "debug.sethdr(): header argument is NULL");
+ return;
+ }
+ hp = VRT_selecthttp(ctx, hdr->where);
+ if (hp == NULL) {
+ VRT_fail(ctx, "debug.sethdr(): header argument "
+ "can not be used here");
+ return;
+ }
+ AN(hdr->what);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
if (s->n == 0) {
- http_Unset(hp, hs->what);
+ http_Unset(hp, hdr->what);
} else {
- b = VRT_StrandsWS(hp->ws, hs->what + 1, s);
+ b = VRT_StrandsWS(hp->ws, hdr->what + 1, s);
if (b == NULL) {
- VSLb(ctx->vsl, SLT_LostHeader, "%s", hs->what + 1);
+ VSLb(ctx->vsl, SLT_LostHeader, "%s", hdr->what + 1);
} else {
if (*b != '\0')
WS_Assert_Allocated(hp->ws, b, strlen(b) + 1);
- http_Unset(hp, hs->what);
+ http_Unset(hp, hdr->what);
http_SetHeader(hp, b);
}
}
diff --git a/vmod/vmod_std.c b/vmod/vmod_std.c
index bb24e04ce..719c5051a 100644
--- a/vmod/vmod_std.c
+++ b/vmod/vmod_std.c
@@ -182,7 +182,16 @@ vmod_collect(VRT_CTX, VCL_HEADER hdr, VCL_STRING sep)
struct http *hp;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ if (hdr == NULL) {
+ VRT_fail(ctx, "std.collect(): header argument is NULL");
+ return;
+ }
hp = VRT_selecthttp(ctx, hdr->where);
+ if (hp == NULL) {
+ VRT_fail(ctx, "std.collect(): header argument "
+ "can not be used here");
+ return;
+ }
http_CollectHdrSep(hp, hdr->what, sep);
}
diff --git a/vmod/vmod_std.vcc b/vmod/vmod_std.vcc
index e9812ee8e..fd0bf1a4a 100644
--- a/vmod/vmod_std.vcc
+++ b/vmod/vmod_std.vcc
@@ -73,6 +73,8 @@ headers, with an additional whitespace for pretty printing.
Care should be taken when collapsing headers. In particular collapsing
``Set-Cookie`` will lead to unexpected results on the browser side.
+Using *hdr* from ``obj.http`` triggers a VCL failure.
+
Examples::
std.collect(req.http.accept);
More information about the varnish-commit
mailing list