r1552 - in trunk/varnish-cache: include lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Mon Jun 25 10:17:26 CEST 2007


Author: phk
Date: 2007-06-25 10:17:25 +0200 (Mon, 25 Jun 2007)
New Revision: 1552

Modified:
   trunk/varnish-cache/include/vrt_obj.h
   trunk/varnish-cache/lib/libvcl/vcc_compile.c
   trunk/varnish-cache/lib/libvcl/vcc_compile.h
   trunk/varnish-cache/lib/libvcl/vcc_parse.c
   trunk/varnish-cache/lib/libvcl/vcc_xref.c
Log:
Make the VCL compiler complain about attempts to access variables outside
their scope.  One example of this is the "req.hash" variable which only
exists in the vcl_hash method.



Modified: trunk/varnish-cache/include/vrt_obj.h
===================================================================
--- trunk/varnish-cache/include/vrt_obj.h	2007-06-25 07:14:08 UTC (rev 1551)
+++ trunk/varnish-cache/include/vrt_obj.h	2007-06-25 08:17:25 UTC (rev 1552)
@@ -26,6 +26,8 @@
 void VRT_l_req_proto(struct sess *, const char *);
 struct backend * VRT_r_req_backend(struct sess *);
 void VRT_l_req_backend(struct sess *, struct backend *);
+const char * VRT_r_req_http_(struct sess *);
+void VRT_l_req_http_(struct sess *, const char *);
 const char * VRT_r_req_hash(struct sess *);
 void VRT_l_req_hash(struct sess *, const char *);
 unsigned VRT_r_obj_valid(struct sess *);
@@ -34,7 +36,5 @@
 void VRT_l_obj_cacheable(struct sess *, unsigned);
 double VRT_r_obj_ttl(struct sess *);
 void VRT_l_obj_ttl(struct sess *, double);
-const char * VRT_r_req_http_(struct sess *);
-void VRT_l_req_http_(struct sess *, const char *);
 const char * VRT_r_resp_http_(struct sess *);
 void VRT_l_resp_http_(struct sess *, const char *);

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.c	2007-06-25 07:14:08 UTC (rev 1551)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.c	2007-06-25 08:17:25 UTC (rev 1552)
@@ -82,7 +82,7 @@
 
 struct method method_tab[] = {
 #define VCL_RET_MAC(l,U,b,n)
-#define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, m },
+#define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, m, VCL_MET_##U },
 #include "vcl_returns.h"
 #undef VCL_MET_MAC
 #undef VCL_RET_MAC
@@ -278,6 +278,7 @@
 			continue;
 		if (memcmp(t->b, v->name, v->len))
 			continue;
+		vcc_AddUses(tl, v);
 		if (v->fmt != HEADER)
 			return (v);
 		return (HeaderVar(tl, t, v));
@@ -645,6 +646,11 @@
 	if (tl->err)
 		return (vcc_DestroyTokenList(tl, NULL));
 
+	/* Check that all variable uses are legal */
+	vcc_CheckUses(tl);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
 	Ff(tl, 0, "\tVRT_free_backends(&VCL_conf);\n");
 
 	/* Emit method functions */

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.h	2007-06-25 07:14:08 UTC (rev 1551)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.h	2007-06-25 08:17:25 UTC (rev 1552)
@@ -127,10 +127,9 @@
 struct method {
 	const char		*name;
 	unsigned		returns;
+	unsigned		bitval;
 };
 
-struct proc;
-
 /*--------------------------------------------------------------------*/
 
 /* vcc_acl.c */
@@ -180,7 +179,7 @@
 void vcc_AddToken(struct tokenlist *tl, unsigned tok, const char *b, const char *e);
 void vcc_FreeToken(struct token *t);
 
-/* vcc_expr.c */
+/* vcc_xref.c */
 void vcc_AddDef(struct tokenlist *tl, struct token *t, enum ref_type type);
 void vcc_AddRef(struct tokenlist *tl, struct token *t, enum ref_type type);
 int vcc_CheckReferences(struct tokenlist *tl);
@@ -189,6 +188,8 @@
 struct proc *vcc_AddProc(struct tokenlist *tl, struct token *t);
 void vcc_ProcAction(struct proc *p, unsigned action, struct token *t);
 int vcc_CheckAction(struct tokenlist *tl);
+void vcc_AddUses(struct tokenlist *tl, struct var *v);
+int vcc_CheckUses(struct tokenlist *tl);
 
 #define ERRCHK(tl)      do { if ((tl)->err) return; } while (0)
 #define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__)

Modified: trunk/varnish-cache/lib/libvcl/vcc_parse.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_parse.c	2007-06-25 07:14:08 UTC (rev 1551)
+++ trunk/varnish-cache/lib/libvcl/vcc_parse.c	2007-06-25 08:17:25 UTC (rev 1552)
@@ -545,6 +545,7 @@
 	tl->indent -= INDENT;
 	Fb(tl, 0, "\n");
 	tl->fb = NULL;
+	tl->curproc = NULL;
 }
 
 /*--------------------------------------------------------------------

Modified: trunk/varnish-cache/lib/libvcl/vcc_xref.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_xref.c	2007-06-25 07:14:08 UTC (rev 1551)
+++ trunk/varnish-cache/lib/libvcl/vcc_xref.c	2007-06-25 08:17:25 UTC (rev 1552)
@@ -55,9 +55,16 @@
 	struct token		*t;
 };
 
+struct procuse {
+	TAILQ_ENTRY(procuse)	list;
+	struct token		*t;
+	struct var		*v;
+};
+
 struct proc {
 	TAILQ_ENTRY(proc)	list;
 	TAILQ_HEAD(,proccall)	calls;
+	TAILQ_HEAD(,procuse)	uses;
 	struct token		*name;
 	unsigned		returns;
 	unsigned		exists;
@@ -180,6 +187,7 @@
 	p = TlAlloc(tl, sizeof *p);
 	assert(p != NULL);
 	TAILQ_INIT(&p->calls);
+	TAILQ_INIT(&p->uses);
 	TAILQ_INSERT_TAIL(&tl->procs, p, list);
 	p->name = t;
 	return (p);
@@ -197,6 +205,20 @@
 }
 
 void
+vcc_AddUses(struct tokenlist *tl, struct var *v)
+{
+	struct procuse *pu;
+
+	if (tl->curproc == NULL)	/* backend */
+		return;
+	pu = TlAlloc(tl, sizeof *pu);
+	assert(pu != NULL);
+	pu->v = v;
+	pu->t = tl->t;
+	TAILQ_INSERT_TAIL(&tl->curproc->uses, pu, list);
+}
+
+void
 vcc_AddCall(struct tokenlist *tl, struct token *t)
 {
 	struct proccall *pc;
@@ -305,3 +327,73 @@
 	return (0);
 }
 
+static struct procuse *
+vcc_FindIllegalUse(struct proc *p, struct method *m)
+{
+	struct procuse *pu;
+
+	TAILQ_FOREACH(pu, &p->uses, list)
+		if (!(pu->v->methods & m->bitval)) 
+			return (pu);
+	return (NULL);
+}
+
+static int
+vcc_CheckUseRecurse(struct tokenlist *tl, struct proc *p, struct method *m)
+{
+	struct proccall *pc;
+	struct procuse *pu;
+
+	pu = vcc_FindIllegalUse(p, m);
+	if (pu != NULL) {
+		vsb_printf(tl->sb,
+		    "Variable \"%.*s\" is not available in %s\n",
+		    PF(pu->t), m->name);
+		vcc_ErrWhere(tl, pu->t); 
+		vsb_printf(tl->sb, "\n...in function \"%.*s\"\n",
+		    PF(p->name));
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	TAILQ_FOREACH(pc, &p->calls, list) {
+		if (vcc_CheckUseRecurse(tl, pc->p, m)) {
+			vsb_printf(tl->sb, "\n...called from \"%.*s\"\n",
+			    PF(p->name));
+			vcc_ErrWhere(tl, pc->t);
+			return (1);
+		}
+	}
+	return (0);
+}
+
+int
+vcc_CheckUses(struct tokenlist *tl)
+{
+	struct proc *p;
+	struct method *m;
+	struct procuse *pu;
+	int i;
+
+	TAILQ_FOREACH(p, &tl->procs, list) {
+		i = IsMethod(p->name);
+		if (i < 0)
+			continue;
+		m = method_tab + i;
+		pu = vcc_FindIllegalUse(p, m);
+		if (pu != NULL) {
+			vsb_printf(tl->sb,
+			    "Variable '%.*s' not accessible in method '%.*s'.",
+			    PF(pu->t), PF(p->name));
+			vsb_cat(tl->sb, "\nAt: ");
+			vcc_ErrWhere(tl, pu->t);
+			return (1);
+		}
+		if (vcc_CheckUseRecurse(tl, p, m)) {
+			vsb_printf(tl->sb,
+			    "\n...which is the \"%s\" method\n", m->name);
+			return (1);
+		}
+	}
+	return (0);
+}
+




More information about the varnish-commit mailing list