Commit da861267 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1552 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent f252bd01
......@@ -26,6 +26,8 @@ const char * VRT_r_req_proto(struct sess *);
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 @@ unsigned VRT_r_obj_cacheable(struct sess *);
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 *);
......@@ -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 @@ FindVar(struct tokenlist *tl, const struct token *t, struct var *vl)
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 @@ vcc_CompileSource(struct vsb *sb, struct source *sp)
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 */
......
......@@ -127,10 +127,9 @@ struct var {
struct method {
const char *name;
unsigned returns;
unsigned bitval;
};
struct proc;
/*--------------------------------------------------------------------*/
/* vcc_acl.c */
......@@ -180,7 +179,7 @@ void vcc__ErrInternal(struct tokenlist *tl, const char *func, unsigned line);
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 @@ void vcc_AddCall(struct tokenlist *tl, struct token *t);
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__)
......
......@@ -545,6 +545,7 @@ Function(struct tokenlist *tl)
tl->indent -= INDENT;
Fb(tl, 0, "\n");
tl->fb = NULL;
tl->curproc = NULL;
}
/*--------------------------------------------------------------------
......
......@@ -55,9 +55,16 @@ struct proccall {
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 @@ vcc_findproc(struct tokenlist *tl, struct token *t)
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);
......@@ -196,6 +204,20 @@ vcc_AddProc(struct tokenlist *tl, struct token *t)
return (p);
}
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)
{
......@@ -305,3 +327,73 @@ vcc_CheckAction(struct tokenlist *tl)
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);
}
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