summaryrefslogtreecommitdiff
path: root/libmu_sieve
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-11-29 18:40:58 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2016-11-29 18:40:58 +0200
commit1186b695bc7c105b19e36bff4c7c9dc04fe30d8f (patch)
tree91a09af7ad23205284e4d996fe5340c2a7b69922 /libmu_sieve
parent7b6fe2abc7d5352f14aa54d50f8bc41660ea32dc (diff)
downloadmailutils-1186b695bc7c105b19e36bff4c7c9dc04fe30d8f.tar.gz
mailutils-1186b695bc7c105b19e36bff4c7c9dc04fe30d8f.tar.bz2
sieve: improve memory allocation
* include/mailutils/sieve.h (mu_sieve_alloc) (mu_sieve_palloc,mu_sieve_prealloc) (mu_sieve_pfree,mu_sieve_pstrdup): Remove. (mu_sieve_mstrdup,mu_sieve_mrealloc) (mu_sieve_mfree): Remove. (mu_sieve_reclaim_t): New typedef. (mu_sieve_calloc,mu_sieve_strdup) (mu_sieve_realloc) (mu_sieve_reclaim_default,mu_sieve_reclaim_list) (mu_sieve_reclaim_value,mu_sieve_reclaim_tag): New functions (mu_sieve_value_create): Change prototype (take mu_sieve_machine_t as first argument) * libmu_sieve/mem.c: New file. * libmu_sieve/Makefile.am: Add new file. * libmu_sieve/comparator.c: Use new allocation functions. * libmu_sieve/prog.c: Likewise. * libmu_sieve/register.c: Likewise. * libmu_sieve/sieve.l: Likewise. * libmu_sieve/sieve.y: Likewise. * libmu_sieve/util.c: Likewise. * doc/texinfo/libmu_sieve.texi: Update (needs revision).
Diffstat (limited to 'libmu_sieve')
-rw-r--r--libmu_sieve/Makefile.am1
-rw-r--r--libmu_sieve/comparator.c4
-rw-r--r--libmu_sieve/mem.c206
-rw-r--r--libmu_sieve/prog.c6
-rw-r--r--libmu_sieve/register.c8
-rw-r--r--libmu_sieve/sieve.l18
-rw-r--r--libmu_sieve/sieve.y53
-rw-r--r--libmu_sieve/util.c108
8 files changed, 259 insertions, 145 deletions
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am
index 1bed3273a..0b06ffe3e 100644
--- a/libmu_sieve/Makefile.am
+++ b/libmu_sieve/Makefile.am
@@ -32,6 +32,7 @@ libmu_sieve_la_SOURCES = \
comparator.c\
encoded.c\
load.c\
+ mem.c\
prog.c\
register.c\
relational.c\
diff --git a/libmu_sieve/comparator.c b/libmu_sieve/comparator.c
index 2ef43cf44..a2ac34b0f 100644
--- a/libmu_sieve/comparator.c
+++ b/libmu_sieve/comparator.c
@@ -338,7 +338,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
tmp = mu_sieve_malloc (mach, sizeof (*tmp));
tmp->tag = TAG_COMPFUN;
- tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun);
+ tmp->arg = mu_sieve_value_create (mach, SVT_POINTER, compfun);
mu_list_append (tags, tmp);
if (matchtype == MU_SIEVE_MATCH_REGEX)
@@ -365,7 +365,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
if (rc)
return rc;
- newval = mu_sieve_value_create (SVT_STRING_LIST, rd.list);
+ newval = mu_sieve_value_create (rd.mach, SVT_STRING_LIST, rd.list);
mu_list_replace (args, val, newval);
}
#ifndef FNM_CASEFOLD
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c
new file mode 100644
index 000000000..f03b06dd5
--- /dev/null
+++ b/libmu_sieve/mem.c
@@ -0,0 +1,206 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2002, 2005-2008, 2010-2012, 2014-2016 Free
+ Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sieve-priv.h>
+
+struct memory_cell
+{
+ void *ptr;
+ void (*reclaim) (void *);
+};
+
+static void
+memory_cell_destroy (void *item)
+{
+ struct memory_cell *mcp = item;
+ if (!mcp->reclaim)
+ abort ();
+ else
+ mcp->reclaim (mcp->ptr);
+ free (mcp);
+}
+
+static int
+memory_cell_cmp (const void *a, const void *b)
+{
+ struct memory_cell const *ma = a;
+ struct memory_cell const *mb = b;
+ return ma->ptr != mb->ptr;
+}
+
+void
+mu_sieve_register_memory (mu_sieve_machine_t mach, void *ptr,
+ mu_sieve_reclaim_t reclaim)
+{
+ struct memory_cell *mcp;
+
+ if (!reclaim)
+ reclaim = mu_sieve_reclaim_default;
+
+ if (!mach->memory_pool)
+ {
+ if (mu_list_create (&mach->memory_pool))
+ mu_sieve_abort (mach);
+ mu_list_set_destroy_item (mach->memory_pool, memory_cell_destroy);
+ mu_list_set_comparator (mach->memory_pool, memory_cell_cmp);
+ }
+ mcp = malloc (sizeof (*mcp));
+ if (!mcp)
+ mu_sieve_abort (mach);
+ mcp->ptr = ptr;
+ mcp->reclaim = reclaim;
+ if (mu_list_append (mach->memory_pool, mcp))
+ {
+ memory_cell_destroy (mcp);
+ mu_sieve_abort (mach);
+ }
+}
+
+void
+mu_sieve_free (mu_sieve_machine_t mach, void *ptr)
+{
+ int rc;
+ struct memory_cell mcell;
+
+ mcell.ptr = ptr;
+ rc = mu_list_remove (mach->memory_pool, &mcell);
+ if (rc)
+ {
+ mu_sieve_error (mach, _("INTERNAL ERROR: trying to free unregistered memory pointer"));
+ abort ();
+ }
+}
+
+void *
+mu_sieve_alloc_memory (mu_sieve_machine_t mach, size_t size,
+ mu_sieve_reclaim_t recfun)
+{
+ char *p = malloc (size);
+ if (!p)
+ {
+ mu_sieve_error (mach, "%s", mu_strerror (errno));
+ mu_sieve_abort (mach);
+ }
+ mu_sieve_register_memory (mach, p, recfun);
+ return p;
+}
+
+void *
+mu_sieve_malloc (mu_sieve_machine_t mach, size_t size)
+{
+ return mu_sieve_alloc_memory (mach, size, mu_sieve_reclaim_default);
+}
+
+void *
+mu_sieve_calloc (mu_sieve_machine_t mach, size_t nmemb, size_t size)
+{
+ char *p = calloc (nmemb, size);
+ if (!p)
+ {
+ mu_sieve_error (mach, "%s", mu_strerror (errno));
+ mu_sieve_abort (mach);
+ }
+ mu_sieve_register_memory (mach, p, mu_sieve_reclaim_default);
+ return p;
+}
+
+char *
+mu_sieve_strdup (mu_sieve_machine_t mach, char const *str)
+{
+ size_t len;
+ char *p;
+
+ if (!str)
+ return NULL;
+ len = strlen (str);
+ p = mu_sieve_malloc (mach, len + 1);
+ memcpy (p, str, len);
+ p[len] = 0;
+ return p;
+}
+
+void *
+mu_sieve_realloc (mu_sieve_machine_t mach, void *ptr, size_t size)
+{
+ int rc;
+ struct memory_cell mcell, *mcp;
+
+ if (!ptr)
+ return mu_sieve_malloc (mach, size);
+
+ mcell.ptr = ptr;
+ rc = mu_list_locate (mach->memory_pool, &mcell, (void **)&mcp);
+ if (rc == MU_ERR_NOENT)
+ {
+ mu_sieve_error (mach, _("INTERNAL ERROR: trying to reallocate unregistered memory pointer"));
+ abort ();
+ }
+ else if (rc)
+ {
+ mu_sieve_error (mach, _("error reallocating memory: %s"),
+ mu_strerror (rc));
+ mu_sieve_abort (mach);
+ }
+
+ ptr = realloc (mcp->ptr, size);
+ if (!ptr)
+ {
+ mu_sieve_error (mach, _("error reallocating memory: %s"),
+ mu_strerror (errno));
+ mu_sieve_abort (mach);
+ }
+ mcp->ptr = ptr;
+
+ return ptr;
+}
+
+void
+mu_sieve_reclaim_default (void *p)
+{
+ free (p);
+}
+
+void
+mu_sieve_reclaim_list (void *p)
+{
+ mu_list_t list = p;
+ mu_list_destroy (&list);
+}
+
+void
+mu_sieve_reclaim_value (void *p)
+{
+ if (!p)
+ return;
+ /* For now, the same as _default. Will change in the future */
+ free (p);
+}
+
+void
+mu_sieve_reclaim_tag (void *p)
+{
+ mu_sieve_runtime_tag_t *tag = p;
+ mu_sieve_reclaim_value (tag->arg);
+}
+
diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c
index 50af4c9dd..8c6bc6d8e 100644
--- a/libmu_sieve/prog.c
+++ b/libmu_sieve/prog.c
@@ -31,7 +31,7 @@ mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op)
{
size_t newsize = mach->progsize + SIEVE_CODE_INCR;
sieve_op_t *newprog =
- mu_sieve_mrealloc (mach, mach->prog, newsize * sizeof mach->prog[0]);
+ mu_sieve_realloc (mach, mach->prog, newsize * sizeof mach->prog[0]);
if (!newprog)
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, _("not enough memory"));
@@ -261,8 +261,8 @@ sv_code_command (struct mu_sieve_machine *mach,
mu_list_create (&list);
mu_list_append (list, val->v.string);
- mu_sieve_mfree (mach, val);
- val = mu_sieve_value_create (SVT_STRING_LIST, list);
+ mu_sieve_free (mach, val);
+ val = mu_sieve_value_create (mach, SVT_STRING_LIST, list);
}
else
{
diff --git a/libmu_sieve/register.c b/libmu_sieve/register.c
index 31e0c8797..acd387645 100644
--- a/libmu_sieve/register.c
+++ b/libmu_sieve/register.c
@@ -89,14 +89,14 @@ mu_sieve_require_test (mu_sieve_machine_t mach, const char *name)
static int
-sieve_register (mu_list_t *pool,
+sieve_register (mu_sieve_machine_t mach,
mu_list_t *list,
const char *name, mu_sieve_handler_t handler,
mu_sieve_data_type *req_arg_types,
mu_sieve_data_type *opt_arg_types,
mu_sieve_tag_group_t *tags, int required)
{
- mu_sieve_register_t *reg = mu_sieve_palloc (pool, sizeof (*reg));
+ mu_sieve_register_t *reg = mu_sieve_malloc (mach, sizeof (*reg));
if (!reg)
return ENOMEM;
@@ -129,7 +129,7 @@ mu_sieve_register_test_ext (mu_sieve_machine_t mach,
mu_sieve_data_type *opt_args,
mu_sieve_tag_group_t *tags, int required)
{
- return sieve_register (&mach->memory_pool,
+ return sieve_register (mach,
&mach->test_list, name, handler,
req_args, opt_args, tags, required);
}
@@ -153,7 +153,7 @@ mu_sieve_register_action_ext (mu_sieve_machine_t mach,
mu_sieve_data_type *opt_args,
mu_sieve_tag_group_t *tags, int required)
{
- return sieve_register (&mach->memory_pool,
+ return sieve_register (mach,
&mach->action_list, name, handler,
req_args, opt_args, tags, required);
}
diff --git a/libmu_sieve/sieve.l b/libmu_sieve/sieve.l
index 43edd6a79..9f684e3e9 100644
--- a/libmu_sieve/sieve.l
+++ b/libmu_sieve/sieve.l
@@ -226,7 +226,7 @@ push_source (const char *name)
if (mu_sieve_locus.mu_file)
{
advance_locus ();
- ctx = mu_sieve_alloc (sizeof (*ctx));
+ ctx = mu_sieve_malloc (mu_sieve_machine, sizeof (*ctx));
ctx->locus = mu_sieve_locus;
ctx->i_node = sieve_source_inode;
ctx->input = input_stream;
@@ -262,7 +262,7 @@ pop_source ()
sieve_source_inode = context_stack->i_node;
RESTORE_BUFFER_STATE (context_stack->state);
ctx = context_stack->prev;
- free (context_stack);
+ mu_sieve_free (mu_sieve_machine, context_stack);
context_stack = ctx;
return 0;
@@ -393,7 +393,7 @@ get_file_name (char *p, char *endp, int *usepath)
}
n = p - startp;
- name = mu_sieve_alloc (n + 1);
+ name = mu_sieve_malloc (mu_sieve_machine, n + 1);
memcpy (name, startp, n);
name[n] = 0;
return name;
@@ -420,7 +420,7 @@ _try_include (void *item, void *data)
}
static void
-sieve_include ()
+sieve_include (void)
{
char *p, *endp = yytext + yyleng, *name;
int usepath;
@@ -440,14 +440,14 @@ sieve_include ()
&& mu_list_foreach (mu_sieve_include_path, _try_include, &p))
{
push_source (p);
- free (name);
+ mu_sieve_free (mu_sieve_machine, name);
free (p);
return;
}
}
push_source (name);
- free (name);
+ mu_sieve_free (mu_sieve_machine, name);
}
static void
@@ -462,7 +462,7 @@ sieve_searchpath (void)
if (name)
{
mu_i_sv_load_add_dir (mu_sieve_machine, name);
- free (name);
+ mu_sieve_free (mu_sieve_machine, name);
}
}
@@ -597,7 +597,7 @@ multiline_begin (void)
break;
len = endp - p;
- multiline_delimiter = mu_sieve_alloc (len + 1);
+ multiline_delimiter = mu_sieve_malloc (mu_sieve_machine, len + 1);
memcpy (multiline_delimiter, p, len);
multiline_delimiter[len] = 0;
}
@@ -635,7 +635,7 @@ ident (const char *text)
static char *
str_unescape (char *text, size_t len)
{
- char *str = mu_sieve_alloc (len);
+ char *str = mu_sieve_malloc (mu_sieve_machine, len);
memcpy (str, text, len - 2);
str[len - 2] = mu_wordsplit_c_unquote_char (text[len - 1]);
str[len - 1] = 0;
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve.y
index 22f0f2037..b60d44fd4 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve.y
@@ -333,23 +333,24 @@ arglist : arg
arg : stringlist
{
- $$ = mu_sieve_value_create (SVT_STRING_LIST, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine,
+ SVT_STRING_LIST, $1);
}
| STRING
{
- $$ = mu_sieve_value_create (SVT_STRING, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
}
| MULTILINE
{
- $$ = mu_sieve_value_create (SVT_STRING, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
}
| NUMBER
{
- $$ = mu_sieve_value_create (SVT_NUMBER, &$1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER, &$1);
}
| TAG
{
- $$ = mu_sieve_value_create (SVT_TAG, $1);
+ $$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG, $1);
}
;
@@ -998,13 +999,7 @@ mu_sieve_machine_init (mu_sieve_machine_t *pmach)
if (!mach)
return ENOMEM;
memset (mach, 0, sizeof (*mach));
- rc = mu_list_create (&mach->memory_pool);
- if (rc)
- {
- free (mach);
- return rc;
- }
-
+ mach->memory_pool = NULL;
rc = mu_opool_create (&mach->string_pool, MU_OPOOL_DEFAULT);
if (rc)
{
@@ -1217,8 +1212,8 @@ mu_sieve_get_daemon_email (mu_sieve_machine_t mach)
void
mu_sieve_set_daemon_email (mu_sieve_machine_t mach, const char *email)
{
- mu_sieve_mfree (mach, (void *)mach->daemon_email);
- mach->daemon_email = mu_sieve_mstrdup (mach, email);
+ mu_sieve_free (mach, (void *)mach->daemon_email);
+ mach->daemon_email = mu_sieve_strdup (mach, email);
}
struct sieve_destr_record
@@ -1267,7 +1262,7 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
mu_list_destroy (&mach->comp_list);
mu_list_destroy (&mach->source_list);
mu_opool_destroy (&mach->string_pool);
- mu_sieve_slist_destroy (&mach->memory_pool);
+ mu_list_destroy (&mach->memory_pool);
free (mach);
*pmach = NULL;
}
@@ -1284,18 +1279,26 @@ with_machine (mu_sieve_machine_t mach, char const *name,
mu_strerr = mach->errstream;
mu_stream_ref (mu_strerr);
- mu_i_sv_register_standard_actions (mach);
- mu_i_sv_register_standard_tests (mach);
- mu_i_sv_register_standard_comparators (mach);
mu_sieve_machine = mach;
+ rc = setjmp (mach->errbuf);
- mu_sieve_stream_save (mach);
- rc = thunk (data);
- mu_sieve_stream_restore (mach);
-
- mu_stream_unref (save_errstr);
- mu_strerr = save_errstr;
- mu_stream_unref (mu_strerr);
+ if (rc == 0)
+ {
+ mach->state = mu_sieve_state_init;
+ mu_i_sv_register_standard_actions (mach);
+ mu_i_sv_register_standard_tests (mach);
+ mu_i_sv_register_standard_comparators (mach);
+
+ mu_sieve_stream_save (mach);
+ rc = thunk (data);
+ mu_sieve_stream_restore (mach);
+
+ mu_stream_unref (save_errstr);
+ mu_strerr = save_errstr;
+ mu_stream_unref (mu_strerr);
+ }
+ else
+ mach->state = mu_sieve_state_error;
return rc;
}
diff --git a/libmu_sieve/util.c b/libmu_sieve/util.c
index 27c7d70ee..3df7a2d89 100644
--- a/libmu_sieve/util.c
+++ b/libmu_sieve/util.c
@@ -25,112 +25,14 @@
#include <stdarg.h>
#include <sieve-priv.h>
-void *
-mu_sieve_alloc (size_t size)
-{
- void *p = malloc (size);
- if (!p)
- {
- mu_error ("not enough memory");
- abort ();
- }
- return p;
-}
-
-void *
-mu_sieve_palloc (mu_list_t *pool, size_t size)
-{
- void *p = malloc (size);
- if (p)
- {
- if (!*pool && mu_list_create (pool))
- {
- free (p);
- return NULL;
- }
- mu_list_append (*pool, p);
- }
- return p;
-}
-
-char *
-mu_sieve_pstrdup (mu_list_t *pool, const char *str)
-{
- size_t len;
- char *p;
-
- if (!str)
- return NULL;
- len = strlen (str);
- p = mu_sieve_palloc (pool, len + 1);
- if (p)
- {
- memcpy (p, str, len);
- p[len] = 0;
- }
- return p;
-}
-
-void *
-mu_sieve_prealloc (mu_list_t *pool, void *ptr, size_t size)
-{
- void *newptr;
-
- if (*pool)
- mu_list_remove (*pool, ptr);
-
- newptr = realloc (ptr, size);
- if (newptr)
- {
- if (!*pool && mu_list_create (pool))
- {
- free (newptr);
- return NULL;
- }
- mu_list_append (*pool, newptr);
- }
- return newptr;
-}
-
-void
-mu_sieve_pfree (mu_list_t *pool, void *ptr)
-{
- if (*pool)
- mu_list_remove (*pool, ptr);
- free (ptr);
-}
-
-void *
-mu_sieve_malloc (mu_sieve_machine_t mach, size_t size)
-{
- return mu_sieve_palloc (&mach->memory_pool, size);
-}
-
-char *
-mu_sieve_mstrdup (mu_sieve_machine_t mach, const char *str)
-{
- return mu_sieve_pstrdup (&mach->memory_pool, str);
-}
-
-void *
-mu_sieve_mrealloc (mu_sieve_machine_t mach, void *ptr, size_t size)
-{
- return mu_sieve_prealloc (&mach->memory_pool, ptr, size);
-}
-
-void
-mu_sieve_mfree (mu_sieve_machine_t mach, void *ptr)
-{
- mu_sieve_pfree (&mach->memory_pool, ptr);
-}
-
+
static int
_destroy_item (void *item, void *data)
{
free (item);
return 0;
}
-
+/* FIXME: Not needed? */
void
mu_sieve_slist_destroy (mu_list_t *plist)
{
@@ -141,9 +43,11 @@ mu_sieve_slist_destroy (mu_list_t *plist)
}
mu_sieve_value_t *
-mu_sieve_value_create (mu_sieve_data_type type, void *data)
+mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
+ void *data)
{
- mu_sieve_value_t *val = mu_sieve_alloc (sizeof (*val));
+ mu_sieve_value_t *val = mu_sieve_alloc_memory (mach, sizeof (*val),
+ mu_sieve_reclaim_value);
val->type = type;
switch (type)

Return to:

Send suggestions and report system problems to the System administrator.