[master] 7afd74d2c Create a list of imports, and complain (harmlessly) if the same vmod is imported in multiple versions.

Poul-Henning Kamp phk at FreeBSD.org
Mon Aug 1 11:07:08 UTC 2022


commit 7afd74d2c75e164dd089b782e3a9ac970316978d
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Aug 1 11:05:44 2022 +0000

    Create a list of imports, and complain (harmlessly) if the same vmod is imported in multiple versions.

diff --git a/bin/varnishtest/tests/m00003.vtc b/bin/varnishtest/tests/m00003.vtc
index c02d80071..1660b43b3 100644
--- a/bin/varnishtest/tests/m00003.vtc
+++ b/bin/varnishtest/tests/m00003.vtc
@@ -158,4 +158,37 @@ filewrite -a ${tmpdir}/libvmod_wrong.so {
 filewrite -a ${tmpdir}/libvmod_wrong.so "\x03"
 varnish v1 -errvcl {Bad vmod stanza} { import wrong; }
 
-shell "rm -f ${tmpdir}/libvmod_wrong.so"
+filewrite ${tmpdir}/libvmod_wrong.so "VMOD_JSON_SPEC\x02"
+filewrite -a ${tmpdir}/libvmod_wrong.so {
+    [
+	[
+	    "$VMOD",
+	    "1.0",
+	    "std",
+	    "Vmod_vmod_std_Func",
+	    "0000000000000000000000000000000000000000000000000000000000000000",
+	    "0000000000000000000000000000000000000000000000000000000000000000",
+	    "15",
+	    "0"
+	], [
+	    "$CPROTO", "/* blabla */"
+	]
+    ]
+}
+filewrite -a ${tmpdir}/libvmod_wrong.so "\x03"
+
+varnish v1 -cliok "param.set vmod_path ${topbuild}/vmod/.libs/"
+varnish v1 -cliok "stop"
+
+filewrite  ${tmpdir}/wrong.vcl {
+	vcl 4.1;
+	import std;
+	import std as foo from "${tmpdir}/libvmod_wrong.so";
+	backend default none;
+}
+
+varnish v1 -cliexpect {Different version of VMOD std already loaded} {
+	vcl.load dupvmod ${tmpdir}/wrong.vcl
+}
+
+shell "rm -f ${tmpdir}/libvmod_wrong.so ${tmpdir}wrong.vcl"
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 3de227b21..a5e3990c4 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -47,51 +47,51 @@
 #include "vcc_vmod.h"
 
 struct vmod_import {
-	unsigned		magic;
-#define VMOD_IMPORT_MAGIC	0x31803a5d
-	const char		*err;
-	struct vsb		*json;
-	char			*path;
+	unsigned			magic;
+#define VMOD_IMPORT_MAGIC		0x31803a5d
+	const char			*err;
+	struct vsb			*json;
+	char				*path;
+	VTAILQ_ENTRY(vmod_import)	list;
 
 	// From $VMOD
-	double			vmod_syntax;
-	char			*name;
-	char			*func_name;
-	char			*file_id;
-	char			*abi;
-	unsigned		major;
-	unsigned		minor;
-
-	struct symbol		*sym;
-	const struct token	*t_mod;
-	struct vjsn		*vj;
-#define STANZA(UU, ll, ss) int n_##ll;
+	double				vmod_syntax;
+	char				*name;
+	char				*func_name;
+	char				*file_id;
+	char				*abi;
+	unsigned			major;
+	unsigned			minor;
+
+	struct symbol			*sym;
+	const struct token		*t_mod;
+	struct vjsn			*vj;
+#define STANZA(UU, ll, ss)		int n_##ll;
 	STANZA_TBL
 #undef STANZA
 };
 
+static VTAILQ_HEAD(,vmod_import) imports = VTAILQ_HEAD_INITIALIZER(imports);
+
 typedef void vcc_do_stanza_f(struct vcc *tl, const struct vmod_import *vim,
     const struct vjsn_val *vv);
 
 static int
-vcc_path_open(void *priv, const char *fn)
+vcc_Extract_JSON(struct vmod_import *vim, const char *filename)
 {
-	struct vmod_import *vim;
 	const char *magic = "VMOD_JSON_SPEC\x02", *p;
 	int c;
 	FILE *f;
 
-	CAST_OBJ_NOTNULL(vim, priv, VMOD_IMPORT_MAGIC);
-	AN(fn);
-
-	vim->json = VSB_new_auto();
-	AN(vim->json);
+	CHECK_OBJ_NOTNULL(vim, VMOD_IMPORT_MAGIC);
+	AN(filename);
 
-	f = fopen(fn, "rb");
+	f = fopen(filename, "rb");
 	if (f == NULL) {
 		vim->err = strerror(errno);
 		return (-1);
 	}
+
 	p = magic;
 	vim->err = "No VMOD JSON found";
 	while (1) {
@@ -110,11 +110,15 @@ vcc_path_open(void *priv, const char *fn)
 			break;
 	}
 
+	vim->json = VSB_new_auto();
+	AN(vim->json);
+
 	while (1) {
 		c = getc(f);
 		if (c == EOF) {
 			AZ(fclose(f));
 			vim->err = "Truncated VMOD JSON";
+			VSB_destroy(&vim->json);
 			return (-1);
 		}
 		if (c == '\x03')
@@ -243,9 +247,10 @@ vcc_ParseJSON(const struct vcc *tl, const char *jsn, struct vmod_import *vim)
  */
 
 static int
-vcc_VmodLoad(const struct vcc *tl, struct vmod_import *vim)
+vcc_VmodLoad(struct vcc *tl, struct vmod_import *vim)
 {
 	static const char *err;
+	struct vmod_import *vim2;
 
 	CHECK_OBJ_NOTNULL(vim, VMOD_IMPORT_MAGIC);
 
@@ -260,6 +265,24 @@ vcc_VmodLoad(const struct vcc *tl, struct vmod_import *vim)
 	if (err != NULL)
 		return (-1);
 
+	VTAILQ_FOREACH(vim2, &imports, list) {
+		if (strcmp(vim->name, vim2->name))
+			continue;
+		if (!strcmp(vim->file_id, vim2->file_id)) {
+			// (Truly) duplicate imports are OK
+			return (0);
+		}
+		VSB_printf(tl->sb,
+		    "Different version of VMOD %.*s already loaded\n",
+		    PF(vim->t_mod));
+		vcc_ErrWhere(tl, vim->t_mod);
+		VSB_printf(tl->sb, "Previous import at:\n");
+		vcc_ErrWhere(tl, vim2->t_mod);
+		vcc_Warn(tl);
+		break;
+	}
+	VTAILQ_INSERT_TAIL(&imports, vim, list);
+
 	return (0);
 }
 
@@ -376,6 +399,17 @@ vcc_vim_destroy(struct vmod_import **vimp)
 	FREE_OBJ(vim);
 }
 
+static int
+vcc_path_open(void *priv, const char *fn)
+{
+	struct vmod_import *vim;
+
+	CAST_OBJ_NOTNULL(vim, priv, VMOD_IMPORT_MAGIC);
+	AN(fn);
+
+	return (vcc_Extract_JSON(vim, fn));
+}
+
 void
 vcc_ParseImport(struct vcc *tl)
 {
diff --git a/lib/libvcc/vcc_vmod_sym.c b/lib/libvcc/vcc_vmod_sym.c
index 65f7f4d6f..ee30197b9 100644
--- a/lib/libvcc/vcc_vmod_sym.c
+++ b/lib/libvcc/vcc_vmod_sym.c
@@ -177,8 +177,10 @@ vcc_VmodSymbols(struct vcc *tl, const struct symbol *sym)
 		if (!vjsn_is_array(vv))
 			continue;
 		vv1 = VTAILQ_FIRST(&vv->children);
+		AN(vv1);
 		assert(vjsn_is_string(vv1));
 		vv2 = VTAILQ_NEXT(vv1, list);
+		AN(vv2);
 		if (!vjsn_is_string(vv2))
 			continue;
 


More information about the varnish-commit mailing list