[master] 2fd71469f vcc: Fix dynamic calls to built-in SUBs and properly check evaluation context
Nils Goroll
nils.goroll at uplex.de
Tue Nov 23 12:31:07 UTC 2021
commit 2fd71469f60e56683723b9fddb6ae34ed9b79997
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Tue Oct 26 13:33:23 2021 +0200
vcc: Fix dynamic calls to built-in SUBs and properly check evaluation context
As a follow-up issue from #3719, it was noticed that dynamic calls to
built-in SUBs did not work.
This issue was caused by more (struct symbol) members missing
initialization in VCC_New().
In turn, it became apparent that the evaluation context check in
vcc_expr5() as tested in v00020.vtc only worked by accident, and only
for built-in subs because (struct symbol).eval was NULL for built-in
subs.
We fix SUB type expression evaluation with a type specific evaluation
function which allows expression evaluation from explicit SUB contexts
only.
Fixes #3720
diff --git a/bin/varnishtest/tests/m00053.vtc b/bin/varnishtest/tests/m00053.vtc
index 97ed034ce..72e54ab89 100644
--- a/bin/varnishtest/tests/m00053.vtc
+++ b/bin/varnishtest/tests/m00053.vtc
@@ -98,6 +98,7 @@ varnish v1 -vcl {
sub vcl_backend_error {
# falling through to None backend would be success
call vcl_backend_response;
+ debug.call(vcl_backend_response);
return (deliver);
}
} -start
@@ -205,6 +206,7 @@ varnish v1 -vcl {
}
sub vcl_init {
+ new vbr = debug.caller(vcl_backend_response);
new c = debug.caller(foo);
}
diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc
index 603f3a251..a5b37eed3 100644
--- a/bin/varnishtest/tests/v00020.vtc
+++ b/bin/varnishtest/tests/v00020.vtc
@@ -31,12 +31,31 @@ varnish v1 -errvcl {Comparison of different types: INT '!=' STRING} {
}
}
-varnish v1 -errvcl {Symbol 'vcl_recv' type (sub) can not be used in expression.} {
+varnish v1 -errvcl {Symbol 'vcl_recv' can only be used as a SUB expression} {
+ backend proforma none;
sub vcl_recv {
set req.http.foo = vcl_recv;
}
}
+varnish v1 -errvcl {Symbol 'vcl_recv' can only be used as a SUB expression} {
+ backend proforma none;
+ sub vcl_recv {
+ return (synth(200));
+ }
+ sub vcl_synth {
+ set req.http.foo = vcl_recv;
+ }
+}
+
+varnish v1 -errvcl {Symbol 'asub' can only be used as a SUB expression} {
+ backend proforma none;
+ sub asub {}
+ sub vcl_recv {
+ set req.http.foo = asub;
+ }
+}
+
varnish v1 -errvcl {Symbol 'acl' type (reserved) can not be used in expression.} {
import std;
sub vcl_recv { call acl; }
diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c
index d954ea8b9..d3acb0383 100644
--- a/lib/libvcc/vcc_compile.c
+++ b/lib/libvcc/vcc_compile.c
@@ -64,6 +64,7 @@
#include "libvcc.h"
#include "vfil.h"
+#include "vct.h"
static const struct method method_tab[] = {
{ "none", 0U, 0},
@@ -869,6 +870,11 @@ VCC_New(void)
sym->rname = strdup(VSB_data(vsb));
AN(sym->rname);
VSB_destroy(&vsb);
+
+ sym->type = SUB;
+ sym->kind = VCC_HandleKind(SUB);
+ AZ(VCT_invalid_name(sym->rname, NULL));
+ sym->eval = vcc_Eval_Sub;
}
tl->sb = VSB_new_auto();
AN(tl->sb);
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 3f3ccc3c0..6ce150c4c 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -351,6 +351,7 @@ sym_act_f vcc_Act_Obj;
void vcc_Expr_Init(struct vcc *tl);
sym_expr_t vcc_Eval_Var;
sym_expr_t vcc_Eval_Handle;
+sym_expr_t vcc_Eval_Sub;
sym_expr_t vcc_Eval_SymFunc;
sym_expr_t vcc_Eval_TypeMethod;
void vcc_Eval_Func(struct vcc *, const struct vjsn_val *,
@@ -377,6 +378,7 @@ void vcc_lex_source(struct vcc *tl, struct source *sp, int eoi);
void vcc_stevedore(struct vcc *vcc, const char *stv_name);
/* vcc_symb.c */
+vcc_kind_t VCC_HandleKind(vcc_type_t fmt);
void VCC_PrintCName(struct vsb *vsb, const char *b, const char *e);
struct symbol *VCC_MkSym(struct vcc *tl, const char *b, vcc_ns_t, vcc_kind_t,
int, int);
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index c2e25c871..598a283b4 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -329,6 +329,29 @@ vcc_Eval_Handle(struct vcc *tl, struct expr **e, struct token *t,
}
}
+void v_matchproto_(sym_expr_t)
+vcc_Eval_Sub(struct vcc *tl, struct expr **e, struct token *t,
+ struct symbol *sym, vcc_type_t type)
+{
+
+ (void)t;
+ (void)tl;
+ AN(sym->rname);
+ AZ(type->stringform);
+
+ assert (sym->type == SUB);
+
+ if (type == SUB) {
+ *e = vcc_mk_expr(sym->type, "%s", sym->rname);
+ (*e)->constant = EXPR_CONST;
+ return;
+ }
+
+ VSB_printf(tl->sb, "Symbol '%s' can only be used as a %s expression\n",
+ sym->name, sym->type->name);
+ vcc_ErrWhere(tl, tl->t);
+}
+
/*--------------------------------------------------------------------
*/
diff --git a/lib/libvcc/vcc_symb.c b/lib/libvcc/vcc_symb.c
index 5125cda3e..25d824b91 100644
--- a/lib/libvcc/vcc_symb.c
+++ b/lib/libvcc/vcc_symb.c
@@ -76,7 +76,7 @@ struct symtab {
VTAILQ_HEAD(,symbol) symbols;
};
-static vcc_kind_t
+vcc_kind_t
VCC_HandleKind(vcc_type_t fmt)
{
if (fmt == ACL) return (SYM_ACL);
@@ -510,7 +510,10 @@ VCC_GlobalSymbol(struct symbol *sym, vcc_type_t type)
sym->kind = VCC_HandleKind(sym->type);
if (sym->kind != SYM_NONE) {
AZ(VCT_invalid_name(sym->rname, NULL));
- sym->eval = vcc_Eval_Handle;
+ if (type == SUB)
+ sym->eval = vcc_Eval_Sub;
+ else
+ sym->eval = vcc_Eval_Handle;
} else {
WRONG("Wrong kind of global symbol");
}
More information about the varnish-commit
mailing list