[master] 3c68fa77e Fix callling a dynamic sub for object methods

Nils Goroll nils.goroll at uplex.de
Wed Feb 17 19:20:03 UTC 2021


commit 3c68fa77ecc5ed1b254abde8b692f2793dc0ea5e
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Tue Feb 16 17:52:52 2021 +0100

    Fix callling a dynamic sub for object methods
    
    7ec28f1ae91bd39e6e89beb7dffd4248c5054414 did not work with object
    methods because we need a partial symbol table lookup to identify them,
    otherwise the symbol kind we find is just SUB for the method's return
    value.
    
    Additions to the test case and vmod_debug by @slimhazard, thank you
    
    Fixes #3521

diff --git a/bin/varnishtest/tests/m00053.vtc b/bin/varnishtest/tests/m00053.vtc
index 68034edbc..d5c501ea4 100644
--- a/bin/varnishtest/tests/m00053.vtc
+++ b/bin/varnishtest/tests/m00053.vtc
@@ -192,3 +192,46 @@ logexpect l3 -wait
 client c4 -wait
 client c5 -wait
 client c6 -wait
+
+varnish v1 -vcl {
+	import debug;
+	backend b None;
+
+	sub foo {
+		set resp.http.Foo = "Called";
+	}
+
+	sub vcl_init {
+		new c = debug.caller(foo);
+	}
+
+	sub vcl_recv {
+		return (synth(200));
+	}
+
+	sub vcl_synth {
+		if (req.url == "/call") {
+			call c.xsub();
+		} else {
+			c.call();
+		}
+		return (deliver);
+	}
+}
+
+client c1 {
+	txreq -url "/call"
+	rxresp
+	expect resp.status == 200
+	expect resp.http.Foo == "Called"
+} -start
+
+client c2 {
+	txreq
+	rxresp
+	expect resp.status == 200
+	expect resp.http.Foo == "Called"
+} -start
+
+client c1 -wait
+client c2 -wait
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index 71c9b91db..57a2f6daf 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -50,8 +50,8 @@ vcc_act_call(struct vcc *tl, struct token *t, struct symbol *sym)
 	(void)t;
 	ExpectErr(tl, ID);
 	t0 = tl->t;
-	sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE, SYMTAB_NOERR, XREF_REF);
-
+	sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE, SYMTAB_PARTIAL_NOERR,
+	    XREF_REF);
 	if (sym == NULL)
 		sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_SUB, SYMTAB_CREATE,
 		    XREF_REF);
diff --git a/vmod/vmod_debug.c b/vmod/vmod_debug.c
index 25ce2f76e..8f123c276 100644
--- a/vmod/vmod_debug.c
+++ b/vmod/vmod_debug.c
@@ -1331,3 +1331,62 @@ xyzzy_total_recall(VRT_CTX)
 
 	return (wrong);
 }
+
+/*---------------------------------------------------------------------*/
+
+struct VPFX(debug_caller) {
+       unsigned        magic;
+#define DEBUG_CALLER_MAGIC 0xb47f3449
+       VCL_SUB         sub;
+};
+
+VCL_VOID v_matchproto_(td_xyzzy_debug_caller__init)
+xyzzy_caller__init(VRT_CTX, struct VPFX(debug_caller) **callerp,
+    const char *name, VCL_SUB sub)
+{
+	struct VPFX(debug_caller) *caller;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	AN(callerp);
+	AZ(*callerp);
+	AN(name);
+	AN(sub);
+
+	ALLOC_OBJ(caller, DEBUG_CALLER_MAGIC);
+	AN(caller);
+	*callerp = caller;
+	caller->sub = sub;
+}
+
+VCL_VOID v_matchproto_(td_xyzzy_debug_caller__fini)
+xyzzy_caller__fini(struct VPFX(debug_caller) **callerp)
+{
+	struct VPFX(debug_caller) *caller;
+
+	if (callerp == NULL || *callerp == NULL)
+		return;
+	CHECK_OBJ(*callerp, DEBUG_CALLER_MAGIC);
+	caller = *callerp;
+	*callerp = NULL;
+	FREE_OBJ(caller);
+}
+
+VCL_VOID v_matchproto_(td_xyzzy_debug_caller_call)
+xyzzy_caller_call(VRT_CTX, struct VPFX(debug_caller) *caller)
+{
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(caller, DEBUG_CALLER_MAGIC);
+	AN(caller->sub);
+
+	VRT_call(ctx, caller->sub);
+}
+
+VCL_SUB v_matchproto_(td_xyzzy_debug_caller_sub)
+xyzzy_caller_xsub(VRT_CTX, struct VPFX(debug_caller) *caller)
+{
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(caller, DEBUG_CALLER_MAGIC);
+	AN(caller->sub);
+
+	return (caller->sub);
+}
diff --git a/vmod/vmod_debug.vcc b/vmod/vmod_debug.vcc
index 45fc1fdee..c15079630 100644
--- a/vmod/vmod_debug.vcc
+++ b/vmod/vmod_debug.vcc
@@ -340,3 +340,9 @@ To test *WRONG* behavior
 $Function SUB total_recall()
 
 To test *WRONG* behavior
+
+$Object caller(SUB)
+
+$Method VOID .call()
+
+$Method SUB .xsub()


More information about the varnish-commit mailing list