From 12073622e35a6773d926b7d1bf9f597752d797b0 Mon Sep 17 00:00:00 2001 From: kpfleming Date: Mon, 16 Feb 2009 21:10:38 +0000 Subject: fix a flaw in the ast_string_field_build() family of API calls; these functions made no attempt to reuse the space already allocated to a field, so every time the field was written it would allocate new space, leading to what appeared to be a memory leak. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@176216 f38db490-d61c-443f-a65b-d21fe96a405b --- main/utils.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'main/utils.c') diff --git a/main/utils.c b/main/utils.c index d7863198b..84d53e182 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1256,24 +1256,49 @@ void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr, int index, const char *format, va_list ap1, va_list ap2) { size_t needed; + size_t available; + char *target; - needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1; - - va_end(ap1); + /* if the field already has space allocated, try to reuse it; + otherwise, use the empty space at the end of the current + pool + */ + if (fields[index][0] != '0') { + target = (char *) fields[index]; + available = strlen(fields[index]); + } else { + target = mgr->pool->base + mgr->used; + available = mgr->space; + } - if (needed > mgr->space) { - size_t new_size = mgr->size * 2; + needed = vsnprintf(target, available, format, ap1) + 1; - while (new_size < needed) - new_size *= 2; + va_end(ap1); - if (add_string_pool(mgr, new_size)) - return; + if (needed > available) { + /* if the space needed can be satisfied by using the current + pool (which could only occur if we tried to use the field's + allocated space and failed), then use that space; otherwise + allocate a new pool + */ + if (needed <= mgr->space) { + target = mgr->pool->base + mgr->used; + } else { + size_t new_size = mgr->size * 2; + + while (new_size < needed) + new_size *= 2; + + if (add_string_pool(mgr, new_size)) + return; + + target = mgr->pool->base + mgr->used; + } - vsprintf(mgr->pool->base + mgr->used, format, ap2); + vsprintf(target, format, ap2); } - fields[index] = mgr->pool->base + mgr->used; + fields[index] = target; mgr->used += needed; mgr->space -= needed; } -- cgit v1.2.3