diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-05-15 09:55:55 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-05-15 09:55:55 +0000 |
commit | ea5d13c2fb8aa92f299e37116623e3ef881c1296 (patch) | |
tree | c90d99a9c2dc890d23a8312083cfeae7f8034d8a /mfd/prog.c | |
parent | c4711d10e376605b3dcce187a5d7de718fe93ecf (diff) | |
download | mailfromd-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 (limited to 'mfd/prog.c')
-rw-r--r-- | mfd/prog.c | 264 |
1 files changed, 182 insertions, 82 deletions
@@ -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 = ®tab[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 = ®tab[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 = ®tab[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; } |