[6.0] 15ed6cc87 Fail VCL loading if VMOD objects are left uninitialized.

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Wed Jul 10 07:42:10 UTC 2019


commit 15ed6cc87a98648a115c11e25a84d4e51f2315c0
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
    
    Conflicts:
            lib/libvmod_debug/vmod.vcc

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 71016bc89..50288c6ef 100644
--- a/lib/libvcc/vcc_compile.c
+++ b/lib/libvcc/vcc_compile.c
@@ -294,6 +294,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");
@@ -318,6 +319,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");
@@ -745,6 +753,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 3a98c76e0..52e0dd282 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 00f0cb0d0..04537f161 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 32d4e6f2e..e92cf521e 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -500,6 +500,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()
@@ -720,6 +721,9 @@ class FunctionStanza(Stanza):
 
 class ObjectStanza(Stanza):
     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
 
@@ -778,6 +782,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 04d0088d9..12f309f38 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -207,7 +207,7 @@ $Function VOID sethdr(HEADER, STRANDS)
 
 Set the given header with the concatenation of the given strings.
 
-$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 9038bcb81..3388fab4e 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_()
@@ -202,8 +201,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