summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2008-03-09 10:04:03 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2008-03-09 10:04:03 (GMT)
commit14cc2f2806c7b66992ca4a41d6f8da6020931194 (patch) (side-by-side diff)
treef757e0b384ec5980da28790150f888e67f35fedb
parent17e8d87f2b9ece032bc4408b89918f0b366abc85 (diff)
downloadmailfromd-14cc2f2806c7b66992ca4a41d6f8da6020931194.tar.gz
mailfromd-14cc2f2806c7b66992ca4a41d6f8da6020931194.tar.bz2
Name clashes between constants and variables went unnoticed by the
compiler. Bug reported by Thomas Lynch. Fix this and rename exception codes to minimize chances of such clashes. * src/symtab.c (lookup_or_install): Allow to search using state masks. (variable_or_constant_lookup): New function. (constant_lookup): Return const struct constant *. (constant_lookup_value): New function. * src/lex.l (get_const): Remove. (variable_or_const): New function. * src/gram.y: Display warnings on a clash of constant and variable names. (VARIABLE): Change union type to var. Modify `variable' production accordingly. * src/mailfromd.h (_SYM_COUNT,SYM_MASK,SYM_BITS): New defines. (constant_lookup): Return const struct constant *. (constant_lookup_value): New function. (variable_or_constant_lookup): New function. * src/status.mfi: Prefix exception codes with `e_' to avoid name clashes. Provide backward-compatible constants. * mflib/match_dnsbl.mf (match_dnsbl): Rename range to iprange to avoid name clashes with the exception code. Remove buggy conditions. Provide a correctly working replacement for them if the m3 symbol `COMPAT_4_3' is defined. * mflib/match_rhsbl.mf (match_rhsbl): Rename range to iprange to avoid name clashes with the exception code. Remove buggy conditions. Provide a correctly working replacement for them if the m3 symbol `COMPAT_4_3' is defined. * mflib/match_cidr.mf, mflib/safedb.mf4, tests/etc/catch.rc, tests/etc/catch01.rc: Use new exception codes. git-svn-id: file:///svnroot/mailfromd/branches/release_4_3_patches@1627 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog36
-rw-r--r--mflib/match_cidr.mf4
-rw-r--r--mflib/match_dnsbl.mf20
-rw-r--r--mflib/match_rhsbl.mf12
-rw-r--r--mflib/safedb.mf46
-rw-r--r--src/gram.y50
-rw-r--r--src/lex.l41
-rw-r--r--src/mailfromd.h10
-rw-r--r--src/status.mfi20
-rw-r--r--src/symtab.c38
-rw-r--r--tests/etc/catch.rc4
-rw-r--r--tests/etc/catch01.rc6
12 files changed, 187 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index f1ecc13..9abbf87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2008-03-09 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ Name clashes between constants and variables went unnoticed by the
+ compiler. Bug reported by Thomas Lynch.
+ Fix this and rename exception codes to minimize chances of such
+ clashes.
+
+ * src/symtab.c (lookup_or_install): Allow to search using state
+ masks.
+ (variable_or_constant_lookup): New function.
+ (constant_lookup): Return const struct constant *.
+ (constant_lookup_value): New function.
+ * src/lex.l (get_const): Remove.
+ (variable_or_const): New function.
+ * src/gram.y: Display warnings on a clash of constant and variable
+ names.
+ (VARIABLE): Change union type to var. Modify `variable' production
+ accordingly.
+ * src/mailfromd.h (_SYM_COUNT,SYM_MASK,SYM_BITS): New defines.
+ (constant_lookup): Return const struct constant *.
+ (constant_lookup_value): New function.
+ (variable_or_constant_lookup): New function.
+ * src/status.mfi: Prefix exception codes with `e_' to avoid name
+ clashes.
+ Provide backward-compatible constants.
+ * mflib/match_dnsbl.mf (match_dnsbl): Rename range to iprange to
+ avoid name clashes with the exception code.
+ Remove buggy conditions. Provide a correctly working replacement
+ for them if the m3 symbol `COMPAT_4_3' is defined.
+ * mflib/match_rhsbl.mf (match_rhsbl): Rename range to iprange to
+ avoid name clashes with the exception code.
+ Remove buggy conditions. Provide a correctly working replacement
+ for them if the m3 symbol `COMPAT_4_3' is defined.
+ * mflib/match_cidr.mf, mflib/safedb.mf4, tests/etc/catch.rc,
+ tests/etc/catch01.rc: Use new exception codes.
+
2008-03-01 Sergey Poznyakoff <gray@gnu.org.ua>
* src/prog.c, src/prog.h (advance_pc): Fix type of the 2nd
diff --git a/mflib/match_cidr.mf b/mflib/match_cidr.mf
index bb3470a..24220ab 100644
--- a/mflib/match_cidr.mf
+++ b/mflib/match_cidr.mf
@@ -1,5 +1,5 @@
/* Implementation of match_cidr call
- Copyright (C) 2007 Sergey Poznyakoff
+ Copyright (C) 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ do
if %cidr matches '^(([0-9]{1,3}\.){3}[0-9]{1,3})/([0-9][0-9]?)'
return inet_aton(%ipstr) & len_to_netmask(\3) = inet_aton(\1)
else
- throw invcidr "invalid CIDR (%cidr)"
+ throw e_invcidr "invalid CIDR (%cidr)"
fi
return 0
done
diff --git a/mflib/match_dnsbl.mf b/mflib/match_dnsbl.mf
index 0621a98..53603be 100644
--- a/mflib/match_dnsbl.mf
+++ b/mflib/match_dnsbl.mf
@@ -1,5 +1,6 @@
/* DNSBL checker.
Copyright (C) 2006, 2007 Jan Rafaj
+ Copyright (C) 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,27 +20,26 @@
#pragma regex push +extended
-func match_dnsbl(string address, string zone, string range)
+func match_dnsbl(string address, string zone, string iprange)
returns number
do
- string rbl_ip
- if %range = 'ANY'
- set rbl_ip '127.0.0.0/8'
+ if %iprange = 'ANY'
+ set iprange '127.0.0.0/8'
+ m4_ifdef(`COMPAT_4_3',`
else
- set rbl_ip %range
- if not %range matches '^([0-9]{1,3}\.){3}[0-9]{1,3}$'
+ if not %iprange matches `'''`^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$`'''`
return 0
fi
fi
- if not (%address matches '^([0-9]{1,3}\.){3}[0-9]{1,3}$'
- and %address != %range)
- return 0
+ if not (%address matches `'''`^([0-9]{1,3}\.){3}[0-9]{1,3}$`'''`
+ and %address != %iprange)
+ return 0')
fi
if %address matches
'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$'
- if match_cidr (resolve ("\4.\3.\2.\1", %zone), %rbl_ip)
+ if match_cidr (resolve ("\4.\3.\2.\1", %zone), %iprange)
return 1
else
return 0
diff --git a/mflib/match_rhsbl.mf b/mflib/match_rhsbl.mf
index 9b2a492..d08f103 100644
--- a/mflib/match_rhsbl.mf
+++ b/mflib/match_rhsbl.mf
@@ -1,5 +1,6 @@
/* RHSBL checker.
Copyright (C) 2006, 2007 Jan Rafaj
+ Copyright (C) 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,14 +19,17 @@
#require match_cidr
#pragma regex push +extended
-func match_rhsbl(string email, string zone, string range)
+func match_rhsbl(string email, string zone, string iprange)
returns number
do
- if not (%email matches '@.+$'
- and %range matches '^([0-9]{1,3}\.){3}[0-9]{1,3}$')
+ if %iprange = 'ANY'
+ set iprange '127.0.0.0/8'
+ fi
+ if not (%email matches '@.+$'m4_ifdef(`COMPAT_4_3',`
+ and %iprange matches `'''`^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$'`''))
return 0
fi
- return match_cidr (resolve ((domainpart %email), %zone), %range)
+ return match_cidr (resolve ((domainpart %email), %zone), %iprange)
done
#pragma regex pop
diff --git a/mflib/safedb.mf4 b/mflib/safedb.mf4
index f1d98b8..822d3c7 100644
--- a/mflib/safedb.mf4
+++ b/mflib/safedb.mf4
@@ -1,5 +1,5 @@
/* Safe DB I/O
- Copyright (C) 2007 Sergey Poznyakoff
+ Copyright (C) 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
func safedbget(string name, string key ; string defval, number null)
returns string
do
- catch dbfailure
+ catch e_dbfailure
do
return ""
done
@@ -34,7 +34,7 @@ done
func safedbput(string name, string key, string value ; number null)
do
- catch dbfailure
+ catch e_dbfailure
do
return
done
diff --git a/src/gram.y b/src/gram.y
index 7732007..bb68ded 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -1,6 +1,6 @@
%{
/* This file is part of mailfromd.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -281,7 +281,7 @@ static void register_macro(enum smtp_state tag, const char *macro);
%}
%error-verbose
-%expect 26
+%expect 27
%union {
struct literal *literal;
@@ -341,12 +341,14 @@ static void register_macro(enum smtp_state tag, const char *macro);
%token <locus> SWITCH CASE DEFAULT CONST
%token <locus> FOR LOOP WHILE BREAK NEXT ARGCOUNT
%token <literal> STRING CODE XCODE
-%token <literal> SYMBOL VARIABLE IDENTIFIER
+%token <literal> SYMBOL IDENTIFIER
%token <number> ARG NUMBER BACKREF
%token <builtin> BUILTIN BUILTIN_PROC BUILTIN_P
%token <locus> OR AND EQ NE LT LE GT GE NOT LOGAND LOGOR LOGXOR LOGNOT
%token <function> FUNCTION FUNCTION_PROC FUNCTION_P
%token <type> TYPE
+%token <var> VARIABLE
+%token BOGUS
%left CONCAT
%left OR
@@ -567,6 +569,18 @@ vardecl : TYPE IDENTIFIER
constdecl : CONST IDENTIFIER expr
{
struct value value;
+ struct variable *pvar;
+
+ /* FIXME: This is necessary because constants can be
+ referred to the same way as variables. */
+ if (pvar = variable_lookup($2->text)) {
+ parse_warning(_("Constant name `%s' clashes with a variable name"),
+ $2->text);
+ parse_warning_locus(&pvar->locus,
+ _("This is the location of the "
+ "previous definition"));
+ }
+
if (optimization_level)
optimize($3);
@@ -1025,7 +1039,8 @@ value : STRING
}
| IDENTIFIER
{
- struct value *value_ptr = constant_lookup($1->text);
+ const struct value *value_ptr =
+ constant_lookup_value($1->text);
if (value_ptr)
$$ = *value_ptr;
else {
@@ -1655,17 +1670,15 @@ arglist : expr
variable : VARIABLE
{
- $$ = variable_lookup($1->text);
- if (!$$) {
- parse_error(_("Variable %s is not defined"),
- $1->text);
- YYERROR;
- }
- add_xref($$, get_locus());
+ add_xref($1, get_locus());
}
- ;
+ | BOGUS
+ {
+ YYERROR;
+ }
+ ;
-catch : CATCH catchlist DO
+catch : CATCH catchlist DO
{ $<tie_in>$ = inner_context;
inner_context = context_catch;
catch_nesting++; }
@@ -3440,6 +3453,7 @@ vardecl(const char *name, data_type_t type, storage_class_t sc,
struct locus *loc)
{
struct variable *var;
+ const struct constant *cptr;
if (type == dtype_unspecified) {
parse_error(_("Cannot define variable of unspecified type"));
@@ -3516,6 +3530,16 @@ vardecl(const char *name, data_type_t type, storage_class_t sc,
}
}
+ /* FIXME: This is necessary because constants can be
+ referred to the same way as variables. */
+ if (cptr = constant_lookup(name)) {
+ parse_warning(_("Variable name `%s' clashes with a constant name"),
+ name);
+ parse_warning_locus(&cptr->locus,
+ _("This is the location of the "
+ "previous definition"));
+ }
+
var->type = type;
var->storage_class = sc;
switch (sc) {
diff --git a/src/lex.l b/src/lex.l
index 7b043bf..c33f2a6 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -1,6 +1,6 @@
%{
/* This file is part of mailfromd.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -85,10 +85,26 @@ keyword(int kw)
} while (0)
static int
-get_const(const char *name)
+variable_or_const()
{
- struct value *value_ptr;
- if (value_ptr = constant_lookup(name)) {
+ union {
+ struct variable *vptr;
+ struct constant *cptr;
+ } v;
+ const struct value *value_ptr;
+
+ switch (variable_or_constant_lookup(yylval.literal->text, &v)) {
+ case SYM_UNDEF:
+ parse_error(_("Variable %s is not defined"),
+ yylval.literal->text);
+ return BOGUS;
+
+ case SYM_VARIABLE:
+ yylval.var = v.vptr;
+ return VARIABLE;
+
+ case SYM_CONSTANT:
+ value_ptr = &v.cptr->value;
switch (value_ptr->type) {
case dtype_number:
yylval.number = value_ptr->v.number;
@@ -102,8 +118,8 @@ get_const(const char *name)
abort();
}
}
- return 0;
}
+
static size_t input_line;
@@ -259,19 +275,14 @@ end return keyword(KW_END);
/* Variables */
<INITIAL,ONBLOCK,ML,CML,STR>\%({ICONST}) { return builtin_const(yytext+1); }
<INITIAL,ONBLOCK,ML,CML,STR>\%{IDENT} {
- int rc;
string(yytext + 1, yyleng - 1);
- if ((rc = get_const(yylval.literal->text)) != 0)
- return rc;
- else
- return VARIABLE; }
+ return variable_or_const();
+}
<INITIAL,ONBLOCK,ML,CML,STR>\%\{{IDENT}\} {
- int rc;
string(yytext + 2, yyleng - 3);
- if ((rc = get_const(yylval.literal->text)) != 0)
- return rc;
- else
- return VARIABLE; }
+ return variable_or_const();
+}
+
/* Positional arguments */
<INITIAL,ONBLOCK,ML,CML,STR>\$# {
return ARGCOUNT;
diff --git a/src/mailfromd.h b/src/mailfromd.h
index 20e2d36..54449c4 100644
--- a/src/mailfromd.h
+++ b/src/mailfromd.h
@@ -1,5 +1,5 @@
/* This file is part of mailfromd.
- Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -587,6 +587,9 @@ struct constant {
#define SYM_VARIABLE 3 /* The entry holds a variable */
#define SYM_LITERAL 4 /* A literal */
#define SYM_CONSTANT 5 /* A constant */
+#define _SYM_COUNT 6
+#define SYM_MASK(n) (1<<(n))
+#define SYM_BITS SYM_MASK(_SYM_COUNT)
typedef int (*symbol_enumerator_t)(void *sym, void *data);
int symbol_enumerate(int state, symbol_enumerator_t fun, void *data);
@@ -628,6 +631,8 @@ struct variable *builtin_variable_install(const char *name,
unsigned flags);
void defer_initialize_variable(char *arg, char *val);
+int variable_or_constant_lookup(const char *name, void **dptr);
+
struct function *function_install(const char *name,
size_t parmcnt, size_t optcnt,
data_type_t *parmtypes,
@@ -636,7 +641,8 @@ struct function *function_install(const char *name,
struct function *function_lookup(const char *name);
struct literal *literal_lookup(const char *text);
void define_constant(const char *name, struct value *value, struct locus *loc);
-struct value *constant_lookup(const char *name);
+const struct constant *constant_lookup(const char *name);
+const struct value *constant_lookup_value(const char *name);
struct sym_regex {
struct literal *lit; /* Corresponding literal */
diff --git a/src/status.mfi b/src/status.mfi
index 6218bcd..40ac06f 100644
--- a/src/status.mfi
+++ b/src/status.mfi
@@ -8,4 +8,22 @@ const FAMILY_INET 2
# Exception codes
-%{const %NAME %CODE%}
+%{const e_%NAME %CODE%}
+
+# Backward-compatible definitions
+const success e_success
+const not_found e_not_found
+const failure e_failure
+const temp_failure e_temp_failure
+const ston_conv e_ston_conv
+const divzero e_divzero
+const regcomp e_regcomp
+const invip e_invip
+const invcidr e_invcidr
+const invtime e_invtime
+const dbfailure e_dbfailure
+const range e_range
+const url e_url
+const noresolve e_noresolve
+const ioerr e_ioerr
+const macroundef e_macroundef
diff --git a/src/symtab.c b/src/symtab.c
index c9c3119..cab45cc 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -1,5 +1,5 @@
/* This file is part of mailfromd.
- Copyright (C) 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -172,7 +172,8 @@ static struct symtab *
lookup_or_install(int state, const char *name, int install)
{
unsigned i, pos;
-
+ struct symtab *foundp = NULL;
+
if (!symtable) {
if (install) {
if (rehash())
@@ -187,13 +188,21 @@ lookup_or_install(int state, const char *name, int install)
if ((state == SYM_UNDEF || symtable[i].state == state)
&& strcmp(symtable[i].vp->name, name) == 0)
return &symtable[i];
+ else if ((state & SYM_BITS)
+ && (SYM_MASK(symtable[i].state) & state)
+ && strcmp(symtable[i].vp->name, name) == 0)
+ foundp = &symtable[i];
+
if (++i >= hash_size[hash_num])
i = 0;
if (i == pos)
break;
}
+
+ if ((state & SYM_BITS) && foundp)
+ return foundp;
- if (!install || state == SYM_UNDEF)
+ if (!install || (state == SYM_UNDEF || (state & SYM_BITS)))
return NULL;
if (symtable[i].state == SYM_UNDEF) {
@@ -398,6 +407,18 @@ variable_lookup(const char *name)
return sp ? &sp->vp->variable : NULL;
}
+int
+variable_or_constant_lookup(const char *name, void **dptr)
+{
+ struct symtab *sp = lookup_or_install(
+ SYM_BITS|SYM_MASK(SYM_VARIABLE)|SYM_MASK(SYM_CONSTANT),
+ name, 0);
+ if (!sp)
+ return SYM_UNDEF;
+ *dptr = sp->vp;
+ return sp->state;
+}
+
struct function *
function_install(const char *name, size_t parmcnt, size_t optcnt,
@@ -467,11 +488,18 @@ define_constant(const char *name, struct value *value, struct locus *locus)
sp->vp->constant.value = *value;
}
-struct value *
+const struct constant *
constant_lookup(const char *name)
{
struct symtab *sp = lookup_or_install(SYM_CONSTANT, name, 0);
- return sp ? &sp->vp->constant.value : NULL;
+ return sp ? &sp->vp->constant : NULL;
+}
+
+const struct value *
+constant_lookup_value(const char *name)
+{
+ const struct constant *cptr = constant_lookup(name);
+ return cptr ? &cptr->value : NULL;
}
diff --git a/tests/etc/catch.rc b/tests/etc/catch.rc
index 70be959..1b91a3e 100644
--- a/tests/etc/catch.rc
+++ b/tests/etc/catch.rc
@@ -1,5 +1,5 @@
/* This file is part of Mailfromd -*- mfl -*-
- Copyright (C) 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff
Mailfromd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ set network "127.0.0.0/8"
prog envfrom
do
- catch invip or invcidr
+ catch e_invip or e_invcidr
do
tempfail 450 "Catched condition " $1
done
diff --git a/tests/etc/catch01.rc b/tests/etc/catch01.rc
index 6820be9..966365b 100644
--- a/tests/etc/catch01.rc
+++ b/tests/etc/catch01.rc
@@ -1,5 +1,5 @@
/* This file is part of Mailfromd -*- mfl -*-
- Copyright (C) 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 2006, 2007, 2008 Sergey Poznyakoff
Mailfromd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ set network "127.0.0.0/8"
func safe_cidr(s,s) returns n
do
- catch invip
+ catch e_invip
do
echo "safe_cidr: invalid IP address"
return 0
@@ -31,7 +31,7 @@ done
prog envfrom
do
- catch invip or invcidr
+ catch e_invip or e_invcidr
do
tempfail 450 "Catched condition " $1
done

Return to:

Send suggestions and report system problems to the System administrator.