aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-03-24 22:36:19 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2011-03-25 01:53:22 +0200
commit1a21d080117d2e3468e0056d5972abba4d48b0b9 (patch)
treee563f8e9fe695f4e9229fb30d3f6bca2250b4432
parent05b53f9efe69acfd21454d3d34d6d7e41d9f885f (diff)
downloadmailfromd-1a21d080117d2e3468e0056d5972abba4d48b0b9.tar.gz
mailfromd-1a21d080117d2e3468e0056d5972abba4d48b0b9.tar.bz2
Fix dataseg expansion (see d91911e8).
* mfd/prog.c (eval_environ) <string>: Remove. The pointer is invalidated after dataseg expansion. Keep offset of the last matched string in matchstr instead (data offset is invariant). All callers updated. (expand_dataseg): Remove static qualifier. (instr_memstk, instr_xmemstk): Bugfix. Both functions were not expansion-safe. * mfd/prog.h (expand_dataseg): New proto.
-rw-r--r--mfd/prog.c44
-rw-r--r--mfd/prog.h1
2 files changed, 34 insertions, 11 deletions
diff --git a/mfd/prog.c b/mfd/prog.c
index f1b2a6c2..8f2304ec 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -269,7 +269,8 @@ struct eval_environ {
regmatch_t *matches; /* Match map */
size_t matchcount; /* Number of used entries in matches */
size_t matchsize; /* Total number of entries in matches */
- char *string; /* Last matched string */
+ prog_counter_t matchstr; /* Pointer to the last matched string
+ in the dataseg. */
mu_stream_t stream; /* Capture stream */
size_t line_count; /* Number of lines in stream */
@@ -396,7 +397,7 @@ env_fixup_autos(eval_environ_t env, ptrdiff_t offset)
}
-static int
+int
expand_dataseg(eval_environ_t env, size_t count, const char *errtext)
{
STKVAL *newds;
@@ -769,14 +770,29 @@ instr_memstk(eval_environ_t env)
{
size_t frame = (size_t) get_immediate(env, 0);
long off = (long) get_immediate(env, 1);
- size_t val = env_base(env, frame) + off;
+ size_t val;
+
+ /* The naive approach would be to just
+ push(env, env_base(env, frame) + off)
+
+ However, push() itself might cause dataseg expansion,
+ which would change tos/toh pointers and render the previously
+ computed argument value invalid. The correct way is to push
+ a placeholder value first, thereby occupying stack slot and
+ eventually causing dataseg expansion, and then compute val
+ using actual environment:
+ */
+
+ push(env, 0);
+ val = env_base(env, frame) + off;
+ env->dataseg[env->tos+1] = (STKVAL)val;
+
if (PROG_TRACE_ENGINE)
prog_trace(env, "MEMSTK %lu(%ld)=%lu",
(unsigned long) frame, off,
(unsigned long) val);
advance_pc(env, 2);
- push(env, (STKVAL) val);
}
void
@@ -790,14 +806,18 @@ instr_xmemstk(eval_environ_t env)
{
size_t frame = (size_t) get_arg(env, 1);
long off = (long) get_arg(env, 0);
- size_t val = env_base(env, frame) + off;
+ size_t val;
+
+ /* See comment in instr_memstk, above */
+ push(env, 0);
+ val = env_base(env, frame) + off;
+ env->dataseg[env->tos+1] = (STKVAL)val;
if (PROG_TRACE_ENGINE)
prog_trace(env, "XMEMSTK %lu(%ld)=%lu",
(unsigned long) frame, off,
(unsigned long) val);
adjust_stack(env, 2);
- push(env, (STKVAL) val);
}
void
@@ -848,7 +868,7 @@ instr_backref(eval_environ_t env)
prog_trace(env, "BACKREF %u", (unsigned)get_immediate(env, 0));
advance_pc(env, 1);
- if (!env->matches || !env->string) {
+ if (!env->matches || !env->matchstr) {
/* FIXME: Try to throw exception first:
env_throw(env, mf_no_regex);
*/
@@ -864,11 +884,12 @@ instr_backref(eval_environ_t env)
} else {
char *s;
size_t off;
-
+ const char *str = (const char *) &env->dataseg[env->matchstr];
+
matchlen = env->matches[n].rm_eo - env->matches[n].rm_so;
off = heap_reserve(env, matchlen + 1);
s = (char*) env_data_ref(env, off);
- memcpy(s, env->string + env->matches[n].rm_so, matchlen);
+ memcpy(s, str + env->matches[n].rm_so, matchlen);
s[matchlen] = 0;
push(env, (STKVAL) off);
}
@@ -1300,6 +1321,8 @@ instr_regmatch(eval_environ_t env)
char *string;
get_string_arg(env, 1, &string);
+ env->matchstr = (STKVAL*)string - env->dataseg;
+
adjust_stack(env, 2);
if (PROG_TRACE_ENGINE)
@@ -1318,7 +1341,6 @@ instr_regmatch(eval_environ_t env)
}
v = regexec(re, string, env->matchcount + 1, env->matches, 0);
- env->string = string;
push(env, (STKVAL) (v == 0));
}
@@ -1983,7 +2005,7 @@ env_init(eval_environ_t env)
env->matches = NULL;
env->matchsize = 0;
env->matchcount = 0;
- env->string = NULL;
+ env->matchstr = 0;
env->numautos = 0;
diff --git a/mfd/prog.h b/mfd/prog.h
index cb42bafe..5b3a00f1 100644
--- a/mfd/prog.h
+++ b/mfd/prog.h
@@ -55,6 +55,7 @@ void env_var_inc(eval_environ_t env, size_t off);
const struct locus *env_get_locus(eval_environ_t env);
STKVAL env_get_reg(eval_environ_t env);
char *env_vaptr(eval_environ_t env, size_t off);
+int expand_dataseg(eval_environ_t env, size_t count, const char *errtext);
void *env_get_builtin_priv(eval_environ_t env, int id);
int builtin_priv_register(void *(*init)(void), void (*destroy)(void*),

Return to:

Send suggestions and report system problems to the System administrator.