diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-01-29 20:09:35 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-01-29 20:09:35 +0200 |
commit | 71c8a9513b43e30358a3c5f0448a768d908852f2 (patch) | |
tree | ca723fbefd708e691d55567f593075ac0d9ed62c /src/prog.c | |
parent | 84800d74f3c2855fe80d1bc5060923cdb9046551 (diff) | |
download | mailfromd-71c8a9513b43e30358a3c5f0448a768d908852f2.tar.gz mailfromd-71c8a9513b43e30358a3c5f0448a768d908852f2.tar.bz2 |
Fixes in runtime memory management
* src/builtin/sprintf.bi: Don't use pointer to format: the latter
might be reallocated during stack expansions, and the pointer would
end up pointing to freed memory area. Another way to fix it would be
to make env_register_auto and env_pop_auto global and to mark the
address of pointer with env_register_auto so it would be reallocated
together with format. However, I wouldn't like to expose too much of
the internals of prog.c.
* src/prog.c (env_get_locus)
(heap_obstack_grow,pushs): Fix argument to env_register_auto.
(env_register_auto): Check if the argument points to a memory
location within data segment + stack. This is necessary, because
heap_obstack_grow registers its argument, which at least in one case
is a pointer to an automatic variable (see MF_OBSTACK_1GROW in
builtin/snarf.m4).
(env_pop_auto,env_unregister_autos)
(env_fixup_autos): Make static.
Diffstat (limited to 'src/prog.c')
-rw-r--r-- | src/prog.c | 21 |
1 files changed, 14 insertions, 7 deletions
@@ -381,13 +381,13 @@ static void env_register_auto(eval_environ_t env, void *ptr); void env_get_locus(eval_environ_t env, struct mu_locus_range *locus) { mu_locus_range_init(locus); locus->beg.mu_file = (char*)(env->dataseg + env->locus.file); - env_register_auto(env, (void*) locus->beg.mu_file); + env_register_auto(env, (void*) &locus->beg.mu_file); locus->beg.mu_line = env->locus.line; #if 0 locus->beg.mu_col = env->locus.point; ... #endif } @@ -490,38 +490,45 @@ env_function_cleanup_add(eval_environ_t env, void *data, The auto_ptr array is cleared (by calling env_unregister_autos) after executing each instruction (see eval_environment). */ static void env_register_auto(eval_environ_t env, void *ptr) { + char *addr = *(char**)ptr; + if (env->numautos == MAX_AUTO_PTR) runtime_error(env, "INTERNAL ERROR at %s:%d, please report", __FILE__, __LINE__); + /* Check if address is within the dataseg */ + if (!(addr >= (char*) env->dataseg + && (addr < (char*) (env->dataseg + datasize + env->stack_size)))) + ptr = NULL; env->auto_ptr[env->numautos++] = ptr; } /* Pop the last registered auto variable */ -void +static void env_pop_auto(eval_environ_t env) { env->numautos--; } -void +static void env_unregister_autos(eval_environ_t env) { env->numautos = 0; } -void +static 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]; - mf_c_val(*pptr,str) += offset; /*FIXME*/ + if (pptr) + mf_c_val(*pptr,str) += offset; /*FIXME*/ } } int expand_dataseg(eval_environ_t env, size_t count, const char *errtext) @@ -796,13 +803,13 @@ heap_obstack_finish(eval_environ_t env) void * heap_obstack_grow(eval_environ_t env, void * MFL_DATASEG ptr, size_t size) { size_t words = B2STACK(size); char *ret; - env_register_auto(env, ptr); + env_register_auto(env, (void*) &ptr); if (env->tos - env->toh < words + B2STACK(env->temp_size)) expand_dataseg(env, words, _("memory chunk too big to fit into heap")); ret = (char*) env_data_ref(env, env->temp_start) + env->temp_size; if (ptr) memmove(ret, ptr, size); @@ -826,13 +833,13 @@ env_data_ref(eval_environ_t env, size_t off) void pushs(eval_environ_t env, const char * MFL_DATASEG s) { size_t off; - env_register_auto(env, (void*) s); + env_register_auto(env, (void*) &s); off = heap_reserve(env, strlen(s) + 1); strcpy((char*) env_data_ref(env, off), s); env_pop_auto(env); push(env, (STKVAL) off); } |