From 287a277042d5cdadec64536c8b97c812d39bdc48 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Thu, 23 Jul 2009 16:06:24 +0000 Subject: [PATCH] * serv_migrate.c: message encoding buffer is now static in order to avoid endlessly abusing malloc/free, and hopefully reduce the chances of heap corruption. --- citadel/modules/migrate/serv_migrate.c | 38 ++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/citadel/modules/migrate/serv_migrate.c b/citadel/modules/migrate/serv_migrate.c index 4857f96f6..07027db06 100644 --- a/citadel/modules/migrate/serv_migrate.c +++ b/citadel/modules/migrate/serv_migrate.c @@ -255,6 +255,25 @@ void migr_export_message(long msgnum) { struct CtdlMessage *msg; struct ser_ret smr; + /* We can use a static buffer here because there will never be more than + * one of this operation happening at any given time, and it's really best + * to just keep it allocated once instead of torturing malloc/free. + * Call this function with msgnum "-1" to free the buffer when finished. + */ + static int encoded_alloc = 0; + static char *encoded_msg = NULL; + + if (msgnum < 0) { + if ((encoded_alloc == 0) && (encoded_msg != NULL)) { + free(encoded_msg); + encoded_alloc = 0; + encoded_msg = NULL; + } + return; + } + + /* Ok, here we go ... */ + msg = CtdlFetchMessage(msgnum, 1); if (msg == NULL) return; /* fail silently */ @@ -268,14 +287,21 @@ void migr_export_message(long msgnum) { serialize_message(&smr, msg); CtdlFreeMessage(msg); - int encoded_len = 0; - int encoded_alloc = smr.len * 14 / 10; /* well-tested formula for predicting encoded size */ - char *encoded_msg = malloc(encoded_alloc); + /* Predict the buffer size we need. Expand the buffer if necessary. */ + int encoded_len = smr.len * 15 / 10 ; + if (encoded_len > encoded_alloc) { + encoded_alloc = encoded_len; + encoded_msg = realloc(encoded_msg, encoded_alloc); + } - if (encoded_msg != NULL) { + if (encoded_msg == NULL) { + /* Questionable hack that hopes it'll work next time and we only lose one message */ + encoded_alloc = 0; + } + else { + /* Once we do the encoding we know the exact size */ encoded_len = CtdlEncodeBase64(encoded_msg, (char *)smr.ser, smr.len, 1); client_write(encoded_msg, encoded_len); - free(encoded_msg); } free(smr.ser); @@ -334,6 +360,8 @@ void migr_export_messages(void) { CtdlLogPrintf(CTDL_INFO, "Exported %d messages.\n", count); else CtdlLogPrintf(CTDL_ERR, "Export aborted due to client disconnect! \n"); + + migr_export_message(-1L); /* This frees the encoding buffer */ } -- 2.30.2