summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2008-05-15 09:55:55 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2008-05-15 09:55:55 (GMT)
commitea5d13c2fb8aa92f299e37116623e3ef881c1296 (patch) (side-by-side diff)
treec90d99a9c2dc890d23a8312083cfeae7f8034d8a
parentc4711d10e376605b3dcce187a5d7de718fe93ecf (diff)
downloadmailfromd-ea5d13c2fb8aa92f299e37116623e3ef881c1296.tar.gz
mailfromd-ea5d13c2fb8aa92f299e37116623e3ef881c1296.tar.bz2
Fixup C variables that point to dataseg after expanding it.
Bug reported by Sergey Afonin. * mfd/snarf.m4 (mf_c_argdcl): Produce only C declarations. (mf_c_arginit): New macro. (__mf_c_argdcl_list,__mf_c_arginit_list): New auxiliary macros. (__mf_c_arglist): Rewrite using the above macros. (mf_c_arglist,MF_VA_ARG): Reflect changes to get_.*_arg functions. * mfd/bi_sprintf.m4: Update invocations of MF_VA_ARG. * mfd/prog.c (struct eval_environ): New members auto_ptr and numautos. (env_register_auto, env_unregister_autos, env_fixup_autos): New functions. (expand_dataseg): Call env_fixup_autos. (get_literal, get_string_arg): Change signature. Call env_register_auto. All callers updated. (get_numeric_arg): Change signature for consistency with other get_ functions. All callers updated. (get_pointer_arg): New function. (eval_environment): Call env_unregister_autos after running each instruction. * mfd/prog.h (get_pointer_arg): New function. (get_string_arg, get_numeric_arg): Change prototypes. * mfd/bi_sieve.m4: Minor stylistic fix. * NEWS: Update. * mfd/drivers.c (code_cast): Handle dtype_pointer git-svn-id: file:///svnroot/mailfromd/trunk@1655 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog30
-rw-r--r--NEWS7
-rw-r--r--mfd/bi_sieve.m42
-rw-r--r--mfd/bi_sprintf.m419
-rw-r--r--mfd/drivers.c4
-rw-r--r--mfd/prog.c264
-rw-r--r--mfd/prog.h6
-rw-r--r--mfd/snarf.m470
8 files changed, 283 insertions, 119 deletions
diff --git a/ChangeLog b/ChangeLog
index 9267c9f..3488c91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2008-05-15 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ Fixup C variables that point to dataseg after expanding it.
+ Bug reported by Sergey Afonin.
+
+ * mfd/snarf.m4 (mf_c_argdcl): Produce only C declarations.
+ (mf_c_arginit): New macro.
+ (__mf_c_argdcl_list,__mf_c_arginit_list): New auxiliary macros.
+ (__mf_c_arglist): Rewrite using the above macros.
+ (mf_c_arglist,MF_VA_ARG): Reflect changes to get_.*_arg functions.
+ * mfd/bi_sprintf.m4: Update invocations of MF_VA_ARG.
+ * mfd/prog.c (struct eval_environ): New members auto_ptr and
+ numautos.
+ (env_register_auto, env_unregister_autos, env_fixup_autos): New
+ functions.
+ (expand_dataseg): Call env_fixup_autos.
+ (get_literal, get_string_arg): Change signature. Call
+ env_register_auto. All callers updated.
+ (get_numeric_arg): Change signature for consistency with other
+ get_ functions. All callers updated.
+ (get_pointer_arg): New function.
+ (eval_environment): Call env_unregister_autos after running each
+ instruction.
+ * mfd/prog.h (get_pointer_arg): New function.
+ (get_string_arg, get_numeric_arg): Change prototypes.
+ * mfd/bi_sieve.m4: Minor stylistic fix.
+ * NEWS: Update.
+
+ * mfd/drivers.c (code_cast): Handle dtype_pointer
+
2008-04-13 Sergey Poznyakoff <gray@gnu.org.ua>
* configure.ac: Require Mailutils 1.9.90
diff --git a/NEWS b/NEWS
index 00d4c80..ff1eaaa 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,8 @@
-Mailfromd NEWS -- history of user-visible changes. 2008-04-13
+Mailfromd NEWS -- history of user-visible changes. 2008-05-15
Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
See the end of file for copying conditions.
-Please send Mailfromd bug reports to <bug-gmach@gnu.org.ua>
+Please send Mailfromd bug reports to <bug-mailfromd@gnu.org.ua>
Version 4.9.92 (SVN)
@@ -161,7 +161,8 @@ name and a list of additional groups when the program is run with
* Bugfixes
** Fix program evaluator bug that manifested itself on machines where
sizeof(unsigned long) > sizeof(usnigned).
-
+** Fix stack reallocation.
+
Version 4.4, 2008-03-10
diff --git a/mfd/bi_sieve.m4 b/mfd/bi_sieve.m4
index e97acb6..d859a82 100644
--- a/mfd/bi_sieve.m4
+++ b/mfd/bi_sieve.m4
@@ -152,7 +152,7 @@ MF_DEFUN(sieve, NUMBER, STRING script, OPTIONAL, NUMBER dbg)
mu_sieve_set_logger(mach, _sieve_action_log);
rc = mu_sieve_compile(mach, script);
- if (rc == 0){
+ if (rc == 0) {
mu_stream_t mstr = env_get_stream(env);
mu_attribute_t attr;
mu_message_t msg;
diff --git a/mfd/bi_sprintf.m4 b/mfd/bi_sprintf.m4
index afd63d3..051d2dc 100644
--- a/mfd/bi_sprintf.m4
+++ b/mfd/bi_sprintf.m4
@@ -150,8 +150,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
if (isdigit(*p)) {
char *q = get_num(p, &n);
if (*q == '$') {
- num = (unsigned) MF_VA_ARG(n-1,
- NUMBER);
+ MF_VA_ARG(n-1, NUMBER, num);
p = q + 1;
if (num < 0) {
flags |= FMT_SPACEPFX;
@@ -161,7 +160,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
break;
}
}
- num = MF_VA_ARG(i, NUMBER);
+ MF_VA_ARG(i, NUMBER, num);
i++;
if (num < 0) {
/* A negative field width is taken
@@ -193,14 +192,14 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
if (isdigit(*p)) {
char *q = get_num(p, &n);
if (*q == '$') {
- num = MF_VA_ARG(n-1, NUMBER);
+ MF_VA_ARG(n-1, NUMBER, num);
if (num > 0)
prec = (unsigned) num;
p = q + 1;
break;
}
}
- num = MF_VA_ARG(i, NUMBER);
+ MF_VA_ARG(i, NUMBER, num);
i++;
if (num > 0)
prec = (unsigned) num;
@@ -211,7 +210,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
argnum = i++;
switch (*p) {
case 's':
- str = MF_VA_ARG(argnum,STRING);
+ MF_VA_ARG(argnum, STRING, str);
n = strlen(str);
if (prec && prec < n)
n = prec;
@@ -235,7 +234,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
case 'i':
case 'd':
- num = MF_VA_ARG(argnum,NUMBER);
+ MF_VA_ARG(argnum, NUMBER, num);
if (num < 0) {
negative = 1;
num = - num;
@@ -290,7 +289,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
break;
case 'u':
- num = MF_VA_ARG(argnum,NUMBER);
+ MF_VA_ARG(argnum, NUMBER, num);
/* If a precision is given with a
numeric conversion, the 0 flag is ignored.
*/
@@ -323,7 +322,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
case 'x':
case 'X':
- num = MF_VA_ARG(argnum,NUMBER);
+ MF_VA_ARG(argnum, NUMBER, num);
/* If a precision is given with a
numeric conversion, the 0 flag is ignored.
*/
@@ -369,7 +368,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format)
break;
case 'o':
- num = MF_VA_ARG(argnum,NUMBER);
+ MF_VA_ARG(argnum, NUMBER, num);
/* If a precision is given with a
numeric conversion, the 0 flag is ignored.
*/
diff --git a/mfd/drivers.c b/mfd/drivers.c
index 72c3b89..2263a9e 100644
--- a/mfd/drivers.c
+++ b/mfd/drivers.c
@@ -2163,6 +2163,10 @@ code_cast(struct locus *locus, data_type_t fromtype, data_type_t totype)
case dtype_number:
code_op(opcode_ntos);
break;
+
+ case dtype_pointer:
+ parse_error_locus(locus,
+ _("Casts from pointer are not supported"));
}
return 0;
}
diff --git a/mfd/prog.c b/mfd/prog.c
index 4ed9309..6b86932 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -233,6 +233,10 @@ disable_prog_trace(const char *modlist)
/* Run-time evaluation */
+/* Max. number of C locals to save in struct eval_environ for eventual fixups.
+ See comment to env_fixup_autos, below. */
+#define MAX_AUTO_PTR 128
+
struct eval_environ {
prog_counter_t pc; /* Program counter */
@@ -251,6 +255,10 @@ struct eval_environ {
/* Temporary heap space */
size_t temp_start;
size_t temp_size;
+
+ STKVAL *auto_ptr[MAX_AUTO_PTR]; /* Pointers to C automatic variables
+ referring to dataseg. */
+ size_t numautos; /* Number of entries in auto_ptr. */
/* Sendmail interaction data: */
SMFICTX *ctx; /* Milter Context */
@@ -326,12 +334,52 @@ env_get_stream(eval_environ_t env)
return env->stream;
}
+
+/* A call to expand_dataseg (see below) invalidates any C variables that
+ pointed to dataseg before the call. To avoid dereferencing invalid memory
+ pointers, the addresses of such C variables are stored in env->auto_ptr
+ using env_register_auto (it is done by get_string_arg). When
+ expand_dataseg is called, it calls env_fixup_autos and passes it the
+ offset of new dataseg from old one. env_fixup_autos adds this value to
+ every address in auto_ptr, thereby fixing them.
+
+ The auto_ptr array is cleared (by calling env_unregister_autos) after
+ executing each instruction (see eval_environment).
+ */
+void
+env_register_auto(eval_environ_t env, void *ptr)
+{
+ if (env->numautos == MAX_AUTO_PTR)
+ runtime_error(env, "INTERNAL ERROR at %s:%d, please report",
+ __FILE__, __LINE__);
+ env->auto_ptr[env->numautos++] = ptr;
+}
+
+void
+env_unregister_autos(eval_environ_t env)
+{
+ env->numautos = 0;
+}
+
+void
+env_fixup_autos(eval_environ_t env, ptrdiff_t offset)
+{
+ int i;
+ for (i = 0; i < env->numautos; i++) {
+ STKVAL *pptr = env->auto_ptr[i];
+ *pptr += offset;
+ }
+}
+
+
#define STACK_EXPAND_BLOCK 64
static int
expand_dataseg(eval_environ_t env, size_t count, const char *errtext)
{
STKVAL *newds;
+ ptrdiff_t offset;
+
count = ((count + STACK_EXPAND_BLOCK - 1) / STACK_EXPAND_BLOCK)
* STACK_EXPAND_BLOCK;
newds = realloc(env->dataseg,
@@ -344,6 +392,7 @@ expand_dataseg(eval_environ_t env, size_t count, const char *errtext)
return 1;
}
+ offset = (char*)newds - (char*)env->dataseg;
env->dataseg = newds;
env->stack_size += count;
env->tos += count;
@@ -351,6 +400,7 @@ expand_dataseg(eval_environ_t env, size_t count, const char *errtext)
memmove(newds + env->tos, newds + env->tos - count,
(datasize + env->stack_size - env->tos)
* sizeof newds[0]);
+ env_fixup_autos(env, offset);
mu_error(_("Warning: stack segment expanded, new size=%lu"),
(unsigned long) env->stack_size);
return 0;
@@ -460,10 +510,11 @@ get_immediate(eval_environ_t env, unsigned n)
return prog[env->pc + n + 1];
}
-const char *
-get_literal(eval_environ_t env, unsigned n)
+void
+get_literal(eval_environ_t env, unsigned n, const char **p)
{
- return (char*)(env->dataseg + (size_t) get_immediate(env, n));
+ *p = (char*)(env->dataseg + (size_t) get_immediate(env, n));
+ env_register_auto(env, p);
}
STKVAL
@@ -472,16 +523,23 @@ get_arg(eval_environ_t env, unsigned n)
return env->dataseg[env->tos + n + 1];
}
-char *
-get_string_arg(eval_environ_t env, unsigned n)
+void
+get_string_arg(eval_environ_t env, unsigned n, char **p)
{
- return (char*) (env->dataseg + (size_t) get_arg(env, n));
+ *p = (char*) (env->dataseg + (size_t) get_arg(env, n));
+ env_register_auto(env, p);
}
-size_t
-get_numeric_arg(eval_environ_t env, unsigned n)
+void
+get_numeric_arg(eval_environ_t env, unsigned n, long *np)
+{
+ *np = (long) get_arg(env, n);
+}
+
+void
+get_pointer_arg(eval_environ_t env, unsigned n, void **p)
{
- return (size_t) get_arg(env, n);
+ *p = (void*) get_arg(env, n);
}
void
@@ -589,8 +647,8 @@ pushs(eval_environ_t env, const char *s)
void
instr_locus(eval_environ_t env)
{
- env->locus.file = get_literal(env, 0);
env->locus.line = (size_t) get_immediate(env, 1);
+ get_literal(env, 0, &env->locus.file);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LOCUS");
advance_pc(env, 2);
@@ -741,10 +799,13 @@ dump_backref(prog_counter_t i)
void
instr_ston(eval_environ_t env)
{
- char *s = get_string_arg(env, 0);
+ char *s;
char *p;
- long v = strtol(s, &p, 0);
+ long v;
+ get_string_arg(env, 0, &s);
+ v = strtol(s, &p, 0);
+
adjust_stack(env, 1);
if (PROG_TRACE_ENGINE)
prog_trace(env, "STON %s", s);
@@ -759,7 +820,7 @@ instr_ston(eval_environ_t env)
void
instr_ntos(eval_environ_t env)
{
- long v = (long) get_numeric_arg(env, 0);
+ long v = (long) get_arg(env, 0);
char buf[NUMERIC_BUFSIZE_BOUND];
adjust_stack(env, 1);
@@ -774,8 +835,8 @@ instr_ntos(eval_environ_t env)
void
instr_cmp(eval_environ_t env)
{
- long l = (long) get_numeric_arg(env, 1);
- long r = (long) get_numeric_arg(env, 0);
+ long l = (long) get_arg(env, 1);
+ long r = (long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "CMP %ld %ld", l, r);
@@ -785,8 +846,10 @@ instr_cmp(eval_environ_t env)
void
instr_symbol(eval_environ_t env)
{
- char *symbol = (char *) get_literal(env, 0);
- char *s = env->getsym(env->data, symbol);
+ char *symbol, *s;
+
+ get_literal(env, 0, (const char **)&symbol);
+ s = env->getsym(env->data, symbol);
if (PROG_TRACE_ENGINE)
prog_trace(env, "SYMBOL %s", symbol);
@@ -813,8 +876,8 @@ dump_symbol(prog_counter_t i)
void
instr_eqn(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "EQN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -824,8 +887,9 @@ instr_eqn(eval_environ_t env)
void
instr_eqs(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "EQS %s %s", a, b);
adjust_stack(env, 2);
@@ -835,8 +899,8 @@ instr_eqs(eval_environ_t env)
void
instr_nen(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "NEN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -846,8 +910,10 @@ instr_nen(eval_environ_t env)
void
instr_nes(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "NES %s %s", a, b);
adjust_stack(env, 2);
@@ -857,8 +923,8 @@ instr_nes(eval_environ_t env)
void
instr_ltn(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LTN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -868,8 +934,10 @@ instr_ltn(eval_environ_t env)
void
instr_lts(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LTS %s %s", a, b);
adjust_stack(env, 2);
@@ -879,8 +947,8 @@ instr_lts(eval_environ_t env)
void
instr_len(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LEN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -890,8 +958,10 @@ instr_len(eval_environ_t env)
void
instr_les(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LES %s %s", a, b);
adjust_stack(env, 2);
@@ -901,8 +971,8 @@ instr_les(eval_environ_t env)
void
instr_gtn(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "GTN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -912,8 +982,10 @@ instr_gtn(eval_environ_t env)
void
instr_gts(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "GTS %s %s", a, b);
adjust_stack(env, 2);
@@ -923,8 +995,8 @@ instr_gts(eval_environ_t env)
void
instr_gen(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "GEN %ld %ld", a, b);
adjust_stack(env, 2);
@@ -934,8 +1006,10 @@ instr_gen(eval_environ_t env)
void
instr_ges(eval_environ_t env)
{
- char *a = get_string_arg(env, 1);
- char *b = get_string_arg(env, 0);
+ char *a, *b;
+
+ get_string_arg(env, 1, &a);
+ get_string_arg(env, 0, &b);
if (PROG_TRACE_ENGINE)
prog_trace(env, "GES %s %s", a, b);
adjust_stack(env, 2);
@@ -946,7 +1020,7 @@ instr_ges(eval_environ_t env)
void
instr_bz(eval_environ_t env)
{
- long v = (long) get_numeric_arg(env, 0);
+ long v = (long) get_arg(env, 0);
long off = (long) get_immediate(env, 0);
if (PROG_TRACE_ENGINE)
@@ -966,7 +1040,7 @@ dump_branch (prog_counter_t i)
void
instr_bnz(eval_environ_t env)
{
- long v = (long) get_numeric_arg(env, 0);
+ long v = (long) get_arg(env, 0);
long off = (long) get_immediate(env, 0);
if (PROG_TRACE_ENGINE)
@@ -990,7 +1064,7 @@ instr_jmp(eval_environ_t env)
void
instr_not(eval_environ_t env)
{
- long v = (long) get_numeric_arg(env, 0);
+ long v = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "NOT %ld", v);
adjust_stack(env, 1);
@@ -1001,8 +1075,8 @@ instr_not(eval_environ_t env)
void
instr_logand(eval_environ_t env)
{
- unsigned long a = (unsigned long) get_numeric_arg(env, 1);
- unsigned long b = (unsigned long) get_numeric_arg(env, 0);
+ unsigned long a = (unsigned long) get_arg(env, 1);
+ unsigned long b = (unsigned long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LOGAND %lu %lu", a, b);
@@ -1012,8 +1086,8 @@ instr_logand(eval_environ_t env)
void
instr_logor(eval_environ_t env)
{
- unsigned long a = (unsigned long) get_numeric_arg(env, 1);
- unsigned long b = (unsigned long) get_numeric_arg(env, 0);
+ unsigned long a = (unsigned long) get_arg(env, 1);
+ unsigned long b = (unsigned long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LOGOR %lu %lu", a, b);
@@ -1023,8 +1097,8 @@ instr_logor(eval_environ_t env)
void
instr_logxor(eval_environ_t env)
{
- unsigned long a = (unsigned long) get_numeric_arg(env, 1);
- unsigned long b = (unsigned long) get_numeric_arg(env, 0);
+ unsigned long a = (unsigned long) get_arg(env, 1);
+ unsigned long b = (unsigned long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LOGXOR %lu %lu", a, b);
@@ -1034,7 +1108,7 @@ instr_logxor(eval_environ_t env)
void
instr_lognot(eval_environ_t env)
{
- unsigned long v = (unsigned long) get_numeric_arg(env, 0);
+ unsigned long v = (unsigned long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "LOGNOT %ld", v);
adjust_stack(env, 1);
@@ -1045,8 +1119,8 @@ instr_lognot(eval_environ_t env)
void
instr_add(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "ADD %ld %ld", a, b);
@@ -1056,8 +1130,8 @@ instr_add(eval_environ_t env)
void
instr_sub(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "SUB %ld %ld", a, b);
@@ -1067,8 +1141,8 @@ instr_sub(eval_environ_t env)
void
instr_mul(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "MUL %ld %ld", a, b);
@@ -1078,8 +1152,8 @@ instr_mul(eval_environ_t env)
void
instr_div(eval_environ_t env)
{
- long a = (long) get_numeric_arg(env, 1);
- long b = (long) get_numeric_arg(env, 0);
+ long a = (long) get_arg(env, 1);
+ long b = (long) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "DIV %ld %ld", a, b);
@@ -1092,7 +1166,7 @@ instr_div(eval_environ_t env)
void
instr_neg(eval_environ_t env)
{
- long v = (long) get_numeric_arg(env, 0);
+ long v = (long) get_arg(env, 0);
if (PROG_TRACE_ENGINE)
prog_trace(env, "NEG %ld", v);
adjust_stack(env, 1);
@@ -1133,9 +1207,11 @@ void
instr_regmatch(eval_environ_t env)
{
int v;
- size_t index = (size_t)get_numeric_arg(env, 0);
+ size_t index = (size_t)get_arg(env, 0);
regex_t *re = &regtab[index].re;
- char *string = get_string_arg(env, 1);
+ char *string;
+
+ get_string_arg(env, 1, &string);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
@@ -1165,9 +1241,11 @@ instr_regcomp(eval_environ_t env)
int v;
char buffer[REGEX_STRING_BUFSIZE];
size_t expr_off = (size_t)get_arg(env, 0);
- char *expr = get_string_arg(env, 0);
+ char *expr;
size_t index = (size_t) get_immediate(env, 0);
struct rt_regex *rtx = &regtab[index];
+
+ get_string_arg(env, 0, &expr);
advance_pc(env, 1);
adjust_stack(env, 1);
@@ -1209,8 +1287,10 @@ dump_regcomp(prog_counter_t i)
void
instr_fnmatch(eval_environ_t env)
{
- char *string = get_string_arg(env, 1);
- char *pattern = get_string_arg(env, 0);
+ char *string, *pattern;
+
+ get_string_arg(env, 1, &string);
+ get_string_arg(env, 0, &pattern);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "FNMATCH %s %s", string, pattern);
@@ -1256,8 +1336,10 @@ fn_matcher(const char *string, void *data)
void
instr_fnmatch_mx(eval_environ_t env)
{
- char *string = get_string_arg(env, 1);
- char *pattern = get_string_arg(env, 0);
+ char *string, *pattern;
+
+ get_string_arg(env, 1, &string);
+ get_string_arg(env, 0, &pattern);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
@@ -1275,9 +1357,11 @@ void
instr_regmatch_mx(eval_environ_t env)
{
int rc;
- size_t index = (size_t)get_numeric_arg(env, 0);
+ size_t index = (size_t)get_arg(env, 0);
regex_t *re = &regtab[index].re;
- char *string = get_string_arg(env, 1);
+ char *string;
+
+ get_string_arg(env, 1, &string);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
@@ -1305,9 +1389,12 @@ void
instr_result(eval_environ_t env)
{
sfsistat status = (sfsistat) get_immediate(env, 0);
- char *code = (char *) get_literal(env, 1);
- char *xcode = (char *) get_literal(env, 2);
- char *message = get_string_arg(env, 0);
+ char *code, *xcode;
+ char *message;
+
+ get_string_arg(env, 0, &message);
+ get_literal(env, 1, (const char**)&code);
+ get_literal(env, 2, (const char**)&xcode);
if (PROG_TRACE_ENGINE)
prog_trace(env, "RESULT %d %s %s %s",
@@ -1349,8 +1436,11 @@ instr_header(eval_environ_t env)
{
struct msgmod_closure *hdr = xmalloc (sizeof(*hdr));
enum msgmod_opcode opcode = (enum msgmod_opcode) get_immediate(env, 0);
- const char *name = get_literal(env, 1);
- const char *value = get_string_arg(env, 0);
+ const char *name;
+ char *value;
+
+ get_string_arg(env, 0, &value);
+ get_literal(env, 1, &name);
advance_pc(env, 2);
adjust_stack(env, 1);
@@ -1375,9 +1465,10 @@ dump_header(prog_counter_t i)
void
instr_builtin(eval_environ_t env)
{
- const char *name = get_literal(env, 0);
+ const char *name;
void (*handler)(eval_environ_t) = get_immediate(env, 1);
+ get_literal(env, 0, &name);
if (PROG_TRACE_ENGINE)
prog_trace(env, "BUILTIN %s", name);
advance_pc(env, 2);
@@ -1393,10 +1484,14 @@ dump_builtin(prog_counter_t i)
void
instr_concat(eval_environ_t env)
{
- char *left = get_string_arg(env, 1);
- char *right = get_string_arg(env, 0);
- size_t off = heap_reserve(env, strlen(left) + strlen(right) + 1);
- char *res = (char*) env_data_ref(env, off);
+ char *left, *right;
+ size_t off;
+ char *res;
+
+ get_string_arg(env, 1, &left);
+ get_string_arg(env, 0, &right);
+ off = heap_reserve(env, strlen(left) + strlen(right) + 1);
+ res = (char*) env_data_ref(env, off);
strcat(strcpy(res, left), right);
adjust_stack(env, 2);
@@ -1415,7 +1510,7 @@ void
instr_asgn(eval_environ_t env)
{
STKVAL val = get_arg(env, 1);
- size_t dest = get_numeric_arg(env, 0);
+ size_t dest = (size_t) get_arg(env, 0);
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "ASGN %lu=%lu",
@@ -1569,8 +1664,9 @@ instr_pushreg(eval_environ_t env)
void
instr_funcall(eval_environ_t env)
{
- const char *name = get_literal(env, 0);
+ const char *name;
prog_counter_t pc = (prog_counter_t) get_immediate(env, 1);
+ get_literal(env, 0, &name);
advance_pc(env, 2);
if (PROG_TRACE_ENGINE)
prog_trace(env, "FUNCALL %s (%lu)", name, (unsigned long)pc);
@@ -1753,6 +1849,8 @@ env_init(eval_environ_t env)
env->matchcount = 0;
env->string = NULL;
+ env->numautos = 0;
+
/* Initialize catch functions */
memcpy (env->catch, env->defcatch, sizeof env->catch);
@@ -1805,8 +1903,10 @@ eval_environment(eval_environ_t env, prog_counter_t start)
runtime_error(env, _("pc out of range"));
if (!prog[env->pc])
break;
- if (setjmp(env->catch_jmp) == 0)
+ if (setjmp(env->catch_jmp) == 0) {
(*(prog[env->pc]))(env);
+ env_unregister_autos(env);
+ }
}
return 0;
}
diff --git a/mfd/prog.h b/mfd/prog.h
index a6421de..11f2fda 100644
--- a/mfd/prog.h
+++ b/mfd/prog.h
@@ -31,9 +31,9 @@ void runtime_warning(eval_environ_t env, const char *fmt, ...);
void runtime_error(eval_environ_t env, const char *fmt, ...)
ATTRIBUTE_NORETURN;
STKVAL get_arg(eval_environ_t env, unsigned n);
-#define get_pointer_arg(e,n) ((void*)get_arg(e,n))
-char *get_string_arg(eval_environ_t env, unsigned n);
-size_t get_numeric_arg(eval_environ_t env, unsigned n);
+void get_pointer_arg(eval_environ_t env, unsigned n, void **p);
+void get_string_arg(eval_environ_t env, unsigned n, char **ptr);
+void get_numeric_arg(eval_environ_t env, unsigned n, long *np);
void push(eval_environ_t env, STKVAL val);
STKVAL pop(eval_environ_t env);
STKVAL *env_data_ref(eval_environ_t env, size_t off);
diff --git a/mfd/snarf.m4 b/mfd/snarf.m4
index 3e841c2..b158161 100644
--- a/mfd/snarf.m4
+++ b/mfd/snarf.m4
@@ -82,25 +82,49 @@ m4_define([<__mf_c_getarg>],m4_dnl
$1,POINTER,get_pointer_arg, ERROR )>])
/* mf_c_argdcl(TYPE NAME) -- translate Mailfromd declaration "TYPE NAME"
- * into the corresponding C one, followed by an equals sign, a typecast,
- * and the name of corresponding get_.*_arg function
- * e.g.:
- * mf_c_argdcl(STRING str) => char *str = (char*) get_string_arg
+ * into the corresponding C one:
+ *
+ * mf_c_argdcl(STRING str) => char *str
*/
m4_define([<mf_c_argdcl>],m4_dnl
-[<m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_c_type(\1)>] \2 = ([<__mf_c_type(\1)>]) [<__mf_c_getarg(\1)>])>])
+[<m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_c_type(\1)>] \2)>])
+
+/* mf_c_arginit(TYPE NAME, NUM) -- translate Mailfromd declaration "TYPE NAME"
+ * into the corresponding C initialization:
+ *
+ * mf_c_argdcl(STRING str) => get_string_arg(env, NUM, &str)
+ */
+m4_define([<mf_c_arginit>],m4_dnl
+[<m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_c_getarg(\1)(env, $2, &\2)>])>])
+
+/* __mf_c_argdcl_list(NARG, LIST) -- translate Mailfromd declaration list
+ * into a set of corresponding C variable declarations.
+ * For more details, see mf_c_arglist below.
+ */
+m4_define([<__mf_c_argdcl_list>],m4_dnl
+[<m4_ifelse($2, , ,$2,[<OPTIONAL>],[<m4_dnl
+__mf_c_argdcl_list($1, m4_shift(m4_shift($@)))>],
+[<mf_c_argdcl($2);
+ __mf_c_argdcl_list(m4_incr($1), m4_shift(m4_shift($@)))>])>])
+
+/* __mf_c_arginit_list(NARG, LIST) -- translate Mailfromd declaration list
+ * into a set of corresponding C variable initializations.
+ * For more details, see mf_c_arglist below.
+ */
+m4_define([<__mf_c_arginit_list>],m4_dnl
+[<m4_ifelse($2, , ,$2,[<OPTIONAL>],[<m4_dnl
+__mf_c_arginit_list($1, m4_shift(m4_shift($@)))>],
+[<mf_c_arginit($2, m4_eval($1));
+ __mf_c_arginit_list(m4_incr($1), m4_shift(m4_shift($@)))>])>])
/* __mf_c_arglist(NARG, LIST) -- translate Mailfromd declaration list
- * into a set of corresponding C variable declarations with initializations.
+ * into a set of corresponding C variable declarations and initializations.
* Arguments:
* NARG -- ordinal number of the first variable in LIST
* LIST -- comma-separated list of Mailfromd declarations
*/
-m4_define([<__mf_c_arglist>],m4_dnl
-[<m4_ifelse($2, , ,$2,[<OPTIONAL>],[<m4_dnl
-__mf_c_arglist($1, m4_shift(m4_shift($@)))>],
-[<mf_c_argdcl($2)(env, m4_eval($1));
- __mf_c_arglist(m4_incr($1), m4_shift(m4_shift($@)))>])>])
+m4_define([<__mf_c_arglist>],[<__mf_c_argdcl_list($@)
+__mf_c_arginit_list($@)>])
/* mf_c_arglist(LIST) -- translate Mailfromd declaration list
* into a set of corresponding C variable declarations with initializations.
@@ -108,23 +132,29 @@ __mf_c_arglist($1, m4_shift(m4_shift($@)))>],
* variables.
* E.g.:
* mf_c_arglist(STRING a, NUMBER n) =>
- * char *a = (char*)get_string_arg(env, 0);
- * long n = (long)get_numeric_arg(env, 1);
+ * char *a;
+ * long n;
+ * get_string_arg(env, 0, &a);
+ * get_numeric_arg(env, 1, &n);
* adjust_stack(env, 2);
*
* Or, if the builtin takes optional parameters:
*
* mf_c_arglist(STRING a, NUMBER n) =>
- * long __bi_argcnt = (long)get_numeric_arg(env, 0);
- * char *a = (char*)get_string_arg(env, 1);
- * long n = (long)get_numeric_arg(env, 2);
+ * long __bi_argcnt;
+ * char *a;
+ * long n;
+ * get_string_arg(env, 1, &a);
+ * get_numeric_arg(env, 2, &n);
+ * get_numeric_arg(env, 0, &__bi_argcnt);
* adjust_stack(env, __bi_argcnt + 1);
*/
m4_define([<mf_c_arglist>],m4_dnl
[<
m4_pushdef([<__ARG1__>], m4_ifelse(__MF_VARARGS__,1,1,[<__mf_has_optarg($@)>]))
-m4_ifelse(__ARG1__,0,,[<long __bi_argcnt = (long)get_numeric_arg(env, 0);>])
+m4_ifelse(__ARG1__,0,,[<long __bi_argcnt;>])
__mf_c_arglist(__ARG1__, $@)
+m4_ifelse(__ARG1__,0,,[<get_numeric_arg(env, 0, &__bi_argcnt);>])
adjust_stack(env, m4_ifelse(__ARG1__,0,mf_argcount($@),__bi_argcnt + 1));
m4_popdef([<__ARG1__>])m4_dnl
>])
@@ -432,13 +462,13 @@ m4_ifelse(__MF_VARARGS__,1,[<__mf_va_count>],
)m4_dnl
m4_define([<__mf_error_code>],1)>])>])
-/* MF_VA_ARG(N, TYPE) -- Produce a code for returning Nth argument of the
- given TYPE in a vararg section. */
+/* MF_VA_ARG(N, TYPE, VAR) -- Produce a code for assigning to VAR the Nth
+ argument of the given TYPE in a vararg section. */
m4_define([<MF_VA_ARG>],[<m4_dnl
m4_ifdef([<__MF_VA_START_USED__>],m4_dnl
[<m4_pushdef([<__ARGN__>],[<$1+mf_argcount(__MF_ARGLIST__)>])
((__bi_argcnt > __ARGN__) ?m4_dnl
- __mf_c_getarg($2)(env, __ARGN__ + 1) :m4_dnl
+ __mf_c_getarg($2)(env, __ARGN__ + 1, &$3) :m4_dnl
(MF_THROW(mfe_range, "Argument %d is not supplied", __ARGN__),m4_dnl
(__mf_c_type($2)) 0))m4_dnl
m4_popdef([<__ARGN__>])>],

Return to:

Send suggestions and report system problems to the System administrator.