[master] 9ceeed8aa Fail VCL loading if VMOD objects are left uninitialized.
Poul-Henning Kamp
phk at FreeBSD.org
Tue Feb 5 11:00:16 UTC 2019
commit 9ceeed8aa880bdb3eb0378aee1ace3d2dc6fca0f
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Feb 5 10:58:36 2019 +0000
Fail VCL loading if VMOD objects are left uninitialized.
Allow VMOD writers to permit with NULL_OK flag.
Only call object destructor on initialized objects.
Fixes #2839
diff --git a/bin/varnishtest/tests/r02839.vtc b/bin/varnishtest/tests/r02839.vtc
new file mode 100644
index 000000000..16525a833
--- /dev/null
+++ b/bin/varnishtest/tests/r02839.vtc
@@ -0,0 +1,32 @@
+varnishtest "Test uninitialized vmod objects"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -vcl+backend "" -start
+
+varnish v1 -errvcl "Object vo_null not initialized" {
+ import debug;
+
+ backend default { .host = "127.0.0.1"; }
+
+ sub vcl_init {
+ if (false) {
+ new null = debug.obj();
+ }
+ }
+}
+
+varnish v1 -vcl {
+ import debug;
+
+ backend default { .host = "127.0.0.1"; }
+
+ sub vcl_init {
+ if (false) {
+ new null = debug.obj_opt();
+ }
+ }
+}
diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c
index d9bc4f84b..09c1d4704 100644
--- a/lib/libvcc/vcc_compile.c
+++ b/lib/libvcc/vcc_compile.c
@@ -293,6 +293,7 @@ EmitInitFini(const struct vcc *tl)
{
struct inifin *p, *q = NULL;
unsigned has_event = 0;
+ struct symbol *sy;
Fh(tl, 0, "\n");
Fh(tl, 0, "static unsigned vgc_inistep;\n");
@@ -317,6 +318,13 @@ EmitInitFini(const struct vcc *tl)
if (VSB_len(p->event))
has_event = 1;
}
+ VTAILQ_FOREACH(sy, &tl->sym_objects, sideways) {
+ Fc(tl, 0, "\tif (!%s) {\n", sy->rname);
+ Fc(tl, 0, "\t\tVRT_fail(ctx, "
+ "\"Object %s not initialized\");\n" , sy->rname);
+ Fc(tl, 0, "\t\treturn(1);\n");
+ Fc(tl, 0, "\t}\n");
+ }
Fc(tl, 0, "\treturn(0);\n");
Fc(tl, 0, "}\n");
@@ -744,6 +752,7 @@ VCC_New(void)
VTAILQ_INIT(&tl->tokens);
VTAILQ_INIT(&tl->sources);
VTAILQ_INIT(&tl->procs);
+ VTAILQ_INIT(&tl->sym_objects);
tl->nsources = 0;
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 4e7e94c05..ece13c662 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -134,6 +134,7 @@ struct symbol {
unsigned magic;
#define SYMBOL_MAGIC 0x3368c9fb
VTAILQ_ENTRY(symbol) list;
+ VTAILQ_ENTRY(symbol) sideways;
VTAILQ_HEAD(,symbol) children;
char *name;
@@ -255,6 +256,8 @@ struct vcc {
const char *default_director;
const char *default_probe;
+ VTAILQ_HEAD(, symbol) sym_objects;
+
unsigned unique;
unsigned vmod_count;
};
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 678821429..483411010 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -353,6 +353,7 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
struct vsb *buf;
const struct vjsn_val *vv, *vf;
const char *p;
+ int null_ok = 0;
(void)sym;
ExpectErr(tl, ID);
@@ -380,8 +381,19 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
}
CAST_OBJ_NOTNULL(vv, sy2->eval_priv, VJSN_VAL_MAGIC);
+ // vv = object name
vv = VTAILQ_NEXT(vv, list);
+ // vv = flags
+ assert(vv->type == VJSN_OBJECT);
+ VTAILQ_FOREACH(vf, &vv->children, list)
+ if (!strcmp(vf->name, "NULL_OK") && vf->type == VJSN_TRUE)
+ null_ok = 1;
+ if (!null_ok)
+ VTAILQ_INSERT_TAIL(&tl->sym_objects, sy1, sideways);
+
+ vv = VTAILQ_NEXT(vv, list);
+ // vv = struct name
Fh(tl, 0, "static %s *%s;\n\n", vv->value, sy1->rname);
vv = VTAILQ_NEXT(vv, list);
@@ -412,7 +424,8 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
vf = VTAILQ_FIRST(&vf->children);
vf = VTAILQ_NEXT(vf, list);
ifp = New_IniFin(tl);
- VSB_printf(ifp->fin, "\t\t%s(&%s);", vf->value, sy1->rname);
+ VSB_printf(ifp->fin, "\t\tif (%s)\n", sy1->rname);
+ VSB_printf(ifp->fin, "\t\t\t\t%s(&%s);", vf->value, sy1->rname);
/* Instantiate symbols for the methods */
buf = VSB_new_auto();
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index f7886920c..3ad485273 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -502,6 +502,7 @@ class Stanza(object):
self.doc = doc
self.vcc = vcc
self.rstlbl = None
+ self.null_ok = False
self.methods = None
self.proto = None
self.parse()
@@ -708,6 +709,9 @@ class ObjectStanza(Stanza):
''' $Object TYPE class ( ARGUMENTS ) '''
def parse(self):
+ if self.toks[1] == "NULL_OK":
+ self.toks.pop(1)
+ self.null_ok = True
self.proto = ProtoType(self, retval=False)
self.proto.obj = "x" + self.proto.name
@@ -768,6 +772,7 @@ class ObjectStanza(Stanza):
ll = [
"$OBJ",
self.proto.name,
+ { "NULL_OK": self.null_ok },
"struct %s%s_%s" %
(self.vcc.sympfx, self.vcc.modname, self.proto.name),
]
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 65464fd32..016bca407 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -218,7 +218,7 @@ in nanoseconds.
For comparable results, a higher size run should called first and discarded.
-$Object obj_opt(PRIV_CALL, PRIV_VCL, PRIV_TASK,
+$Object NULL_OK obj_opt(PRIV_CALL, PRIV_VCL, PRIV_TASK,
[STRING s], [BOOL b])
Test object constructor with all the fancy stuff.
diff --git a/lib/libvmod_debug/vmod_debug_obj.c b/lib/libvmod_debug/vmod_debug_obj.c
index 0dea592a3..34eacca75 100644
--- a/lib/libvmod_debug/vmod_debug_obj.c
+++ b/lib/libvmod_debug/vmod_debug_obj.c
@@ -68,7 +68,6 @@ xyzzy_obj__fini(struct xyzzy_debug_obj **op)
AN(op);
AN(*op);
FREE_OBJ(*op);
- *op = NULL;
}
VCL_VOID v_matchproto_()
@@ -204,8 +203,7 @@ xyzzy_obj_opt__fini(struct xyzzy_debug_obj_opt **op)
struct xyzzy_debug_obj_opt *o;
AN(op);
- if (*op == NULL)
- return; /* init has failed */
+ AN(*op);
TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_OPT_MAGIC);
More information about the varnish-commit
mailing list