[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