aboutsummaryrefslogtreecommitdiffstats
path: root/main/utils.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-02-16 21:10:38 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-02-16 21:10:38 +0000
commit12073622e35a6773d926b7d1bf9f597752d797b0 (patch)
treede57f4686ff4467ee70216396596b01677454e70 /main/utils.c
parent72b9f1e076d992895541d1caa584cc85ace45139 (diff)
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
Diffstat (limited to 'main/utils.c')
-rw-r--r--main/utils.c47
1 files changed, 36 insertions, 11 deletions
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;
}