From 44b9961895e11117b8500ae0d070046670f998e6 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 10 Nov 2017 19:26:20 +0000 Subject: [Fix] Plug memory leak when setting email addresses from Lua + Optimize emails addr structure and API MFH: rspamd-1.6 --- src/libmime/email_addr.c | 39 ++++++++--------------------- src/libmime/email_addr.h | 21 ++++++---------- src/libserver/milter.c | 4 +-- src/libserver/task.c | 4 +-- src/lua/lua_task.c | 61 ++++++++++++++++++++++++++++++++------------- test/lua/unit/smtp_addr.lua | 2 +- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/libmime/email_addr.c b/src/libmime/email_addr.c index 9e69b68ec..08071afc8 100644 --- a/src/libmime/email_addr.c +++ b/src/libmime/email_addr.c @@ -20,20 +20,6 @@ #include "printf.h" #include "smtp_parsers.h" -static void -rspamd_email_addr_dtor (struct rspamd_email_address *addr) -{ - if (addr->flags & RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED) { - g_free ((void *)addr->addr); - } - - if (addr->flags & RSPAMD_EMAIL_ADDR_USER_ALLOCATED) { - g_free ((void *)addr->user); - } - - g_free (addr); -} - static void rspamd_email_address_unescape (struct rspamd_email_address *addr) { @@ -92,26 +78,24 @@ rspamd_email_address_from_smtp (const gchar *str, guint len) ret->flags |= RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED; } - REF_INIT_RETAIN (ret, rspamd_email_addr_dtor); - return ret; } return NULL; } -struct rspamd_email_address * -rspamd_email_address_ref (struct rspamd_email_address *addr) +void +rspamd_email_address_free (struct rspamd_email_address *addr) { - REF_RETAIN (addr); + if (addr->flags & RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED) { + g_free ((void *)addr->addr); + } - return addr; -} + if (addr->flags & RSPAMD_EMAIL_ADDR_USER_ALLOCATED) { + g_free ((void *)addr->user); + } -void -rspamd_email_address_unref (struct rspamd_email_address *addr) -{ - REF_RELEASE (addr); + g_free (addr); } static inline void @@ -152,11 +136,8 @@ rspamd_email_address_add (rspamd_mempool_t *pool, elt->flags |= RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED; } - REF_INIT_RETAIN (elt, rspamd_email_addr_dtor); - if (name->len > 0) { elt->name = rspamd_mime_header_decode (pool, name->str, name->len); - elt->name_len = strlen (elt->name); } g_ptr_array_add (ar, elt); @@ -435,7 +416,7 @@ rspamd_email_address_list_destroy (gpointer ptr) struct rspamd_email_address *addr; PTR_ARRAY_FOREACH (ar, i, addr) { - REF_RELEASE (addr); + rspamd_email_address_free (addr); } g_ptr_array_free (ar, TRUE); diff --git a/src/libmime/email_addr.h b/src/libmime/email_addr.h index b4f192ee7..8c9b54713 100644 --- a/src/libmime/email_addr.h +++ b/src/libmime/email_addr.h @@ -28,11 +28,10 @@ enum rspamd_email_address_flags { RSPAMD_EMAIL_ADDR_BRACED = (1 << 2), RSPAMD_EMAIL_ADDR_QUOTED = (1 << 3), RSPAMD_EMAIL_ADDR_EMPTY = (1 << 4), - RSPAMD_EMAIL_ADDR_SMTP = (1 << 5), - RSPAMD_EMAIL_ADDR_HAS_BACKSLASH = (1 << 6), - RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED = (1 << 7), - RSPAMD_EMAIL_ADDR_USER_ALLOCATED = (1 << 8), - RSPAMD_EMAIL_ADDR_HAS_8BIT = (1 << 9), + RSPAMD_EMAIL_ADDR_HAS_BACKSLASH = (1 << 5), + RSPAMD_EMAIL_ADDR_ADDR_ALLOCATED = (1 << 6), + RSPAMD_EMAIL_ADDR_USER_ALLOCATED = (1 << 7), + RSPAMD_EMAIL_ADDR_HAS_8BIT = (1 << 8), }; /* @@ -47,12 +46,9 @@ struct rspamd_email_address { guint raw_len; guint addr_len; - guint user_len; guint domain_len; - guint name_len; - enum rspamd_email_address_flags flags; - - ref_entry_t ref; + guint16 user_len; + guchar flags; }; /** @@ -84,9 +80,6 @@ GPtrArray *rspamd_email_address_from_mime (rspamd_mempool_t *pool, */ void rspamd_email_address_list_destroy (gpointer ptr); -struct rspamd_email_address * rspamd_email_address_ref ( - struct rspamd_email_address *addr); - -void rspamd_email_address_unref (struct rspamd_email_address *addr); +void rspamd_email_address_free (struct rspamd_email_address *addr); #endif /* SRC_LIBMIME_EMAIL_ADDR_H_ */ diff --git a/src/libserver/milter.c b/src/libserver/milter.c index 2cced96ec..b809b89b6 100644 --- a/src/libserver/milter.c +++ b/src/libserver/milter.c @@ -117,7 +117,7 @@ rspamd_milter_session_reset (struct rspamd_milter_session *session, if (session->rcpts) { PTR_ARRAY_FOREACH (session->rcpts, i, cur) { - rspamd_email_address_unref (cur); + rspamd_email_address_free (cur); } g_ptr_array_free (session->rcpts, TRUE); @@ -125,7 +125,7 @@ rspamd_milter_session_reset (struct rspamd_milter_session *session, } if (session->from) { - rspamd_email_address_unref (session->from); + rspamd_email_address_free (session->from); session->from = NULL; } diff --git a/src/libserver/task.c b/src/libserver/task.c index f4fcd8fb1..5986b8567 100644 --- a/src/libserver/task.c +++ b/src/libserver/task.c @@ -241,14 +241,14 @@ rspamd_task_free (struct rspamd_task *task) if (task->rcpt_envelope) { for (i = 0; i < task->rcpt_envelope->len; i ++) { addr = g_ptr_array_index (task->rcpt_envelope, i); - rspamd_email_address_unref (addr); + rspamd_email_address_free (addr); } g_ptr_array_free (task->rcpt_envelope, TRUE); } if (task->from_envelope) { - rspamd_email_address_unref (task->from_envelope); + rspamd_email_address_free (task->from_envelope); } ucl_object_unref (task->messages); diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 4172d60b7..85f5c9902 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -2170,9 +2170,9 @@ lua_push_email_address (lua_State *L, struct rspamd_email_address *addr) lua_settable (L, -3); } - if (addr->name_len > 0) { + if (addr->name) { lua_pushstring (L, "name"); - lua_pushlstring (L, addr->name, addr->name_len); + lua_pushstring (L, addr->name); lua_settable (L, -3); } else { @@ -2218,6 +2218,7 @@ lua_import_email_address (lua_State *L, struct rspamd_task *task, { struct rspamd_email_address *addr; const gchar *p; + gchar *dst; gsize len; g_assert (paddr != NULL); @@ -2226,16 +2227,16 @@ lua_import_email_address (lua_State *L, struct rspamd_task *task, return FALSE; } - addr = rspamd_mempool_alloc0 (task->task_pool, sizeof (*addr)); + addr = g_malloc0 (sizeof (*addr)); lua_pushstring (L, "name"); lua_gettable (L, pos); if (lua_type (L, -1) == LUA_TSTRING) { p = lua_tolstring (L, -1, &len); - addr->name = (const gchar *)rspamd_mempool_alloc (task->task_pool, len); - memcpy ((gchar *)addr->name, p, len); - addr->name_len = len; + dst = rspamd_mempool_alloc (task->task_pool, len + 1); + rspamd_strlcpy (dst, p, len + 1); + addr->name = dst; } lua_pop (L, 1); @@ -2295,19 +2296,26 @@ lua_import_email_address (lua_State *L, struct rspamd_task *task, } else { /* Construct raw addr */ - len = addr->addr_len + addr->name_len + 3; - addr->raw = (const gchar *)rspamd_mempool_alloc (task->task_pool, len); - if (addr->name_len > 0) { - addr->raw_len = rspamd_snprintf ((gchar *)addr->raw, len, "%*s <%*s>", - (int)addr->name_len, addr->name, + len = addr->addr_len + 3; + + if (addr->name) { + len += strlen (addr->name) + 1; + dst = rspamd_mempool_alloc (task->task_pool, len + 1); + + addr->raw_len = rspamd_snprintf (dst, len, "%s <%*s>", + addr->name, (int)addr->addr_len, addr->addr); } else { - addr->raw_len = rspamd_snprintf ((gchar *)addr->raw, len, "<%*s@%*s>", - (int)addr->name_len, addr->name, - (int)addr->addr_len, addr->addr); + dst = rspamd_mempool_alloc (task->task_pool, len + 1); + + addr->raw_len = rspamd_snprintf (dst, len, "<%*s@%*s>", + (int)addr->user_len, addr->user, + (int)addr->domain_len, addr->domain); } + + addr->raw = dst; } lua_pop (L, 1); @@ -2401,13 +2409,19 @@ lua_task_set_recipients (lua_State *L) break; } if (ptrs) { - lua_pushvalue (L, pos); + guint i; + struct rspamd_email_address *tmp; + + PTR_ARRAY_FOREACH (ptrs, i, tmp) { + rspamd_email_address_free (tmp); + } + g_ptr_array_set_size (ptrs, 0); + lua_pushvalue (L, pos); for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) { if (lua_import_email_address (L, task, lua_gettop (L), &addr)) { g_ptr_array_add (ptrs, addr); - addr = NULL; } } @@ -2624,6 +2638,13 @@ lua_task_set_from (lua_State *L) if (addrs) { if (lua_import_email_address (L, task, pos, &addr)) { + guint i; + struct rspamd_email_address *tmp; + + PTR_ARRAY_FOREACH (addrs, i, tmp) { + rspamd_email_address_free (tmp); + } + g_ptr_array_set_size (addrs, 0); g_ptr_array_add (addrs, addr); lua_pushboolean (L, true); @@ -2633,7 +2654,13 @@ lua_task_set_from (lua_State *L) } } else if (paddr) { - if (lua_import_email_address (L, task, pos, paddr)) { + if (lua_import_email_address (L, task, pos, &addr)) { + + if (paddr) { + rspamd_email_address_free (*paddr); + } + + *paddr = addr; lua_pushboolean (L, true); } else { diff --git a/test/lua/unit/smtp_addr.lua b/test/lua/unit/smtp_addr.lua index efac3a2af..4aa7ecd52 100644 --- a/test/lua/unit/smtp_addr.lua +++ b/test/lua/unit/smtp_addr.lua @@ -21,7 +21,7 @@ context("SMTP address check functions", function() int flags; }; struct rspamd_email_address * rspamd_email_address_from_smtp (const char *str, unsigned len); - void rspamd_email_address_unref (struct rspamd_email_address *addr); + void rspamd_email_address_free (struct rspamd_email_address *addr); ]] test("Parse addrs", function() -- cgit v1.2.3