[7.0] 2fd71469f vcc: Fix dynamic calls to built-in SUBs and properly check evaluation context

Nils Goroll nils.goroll at uplex.de
Mon Nov 8 15:11: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