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
parent 006618c0
......@@ -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);
}
......
......@@ -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; }
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
}
/*--------------------------------------------------------------------
*/
......
......@@ -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");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment