]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix unintential memory retention in stringfields.
authorCorey Farrell <git@cfware.com>
Thu, 6 Nov 2014 09:10:47 +0000 (09:10 +0000)
committerCorey Farrell <git@cfware.com>
Thu, 6 Nov 2014 09:10:47 +0000 (09:10 +0000)
* Fix missing / unreachable calls to __ast_string_field_release_active.
* Reset pool->used to zero when the current pool->active reaches zero.

ASTERISK-24307 #close
Reported by: Etienne Lessard
Tested by: ibercom, Etienne Lessard
Review: https://reviewboard.asterisk.org/r/4114/
........

Merged revisions 427380 from http://svn.asterisk.org/svn/asterisk/branches/1.8

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@427381 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/stringfields.h
main/utils.c

index b5fdf9c8ee07ac9a231f7d116122dc3d116bff26..e507183e45221656fab26980e42cbdf9ff25b4d9 100644 (file)
@@ -315,21 +315,23 @@ void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
 */
 #define ast_string_field_ptr_set(x, ptr, data) ast_string_field_ptr_set_by_fields((x)->__field_mgr_pool, (x)->__field_mgr, ptr, data)
 
-#define ast_string_field_ptr_set_by_fields(field_mgr_pool, field_mgr, ptr, data) do {                                   \
-    const char *__d__ = (data);                                         \
-    size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;                              \
-    ast_string_field *__p__ = (ast_string_field *) (ptr);                               \
-    if (__dlen__ == 1) {                                                \
-        __ast_string_field_release_active(field_mgr_pool, *__p__);                  \
-        *__p__ = __ast_string_field_empty;                                  \
-    } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) ||                         \
-           (!__ast_string_field_ptr_grow(&field_mgr, &field_mgr_pool, __dlen__, __p__)) ||   \
-           (*__p__ = __ast_string_field_alloc_space(&field_mgr, &field_mgr_pool, __dlen__))) {   \
-        if (*__p__ != (*ptr)) {                                         \
-            __ast_string_field_release_active(field_mgr_pool, (*ptr));              \
-        }                                                   \
-        memcpy(* (void **) __p__, __d__, __dlen__);                             \
-    }                                                       \
+#define ast_string_field_ptr_set_by_fields(field_mgr_pool, field_mgr, ptr, data) do {            \
+    const char *__d__ = (data);                                                                  \
+    size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;                                           \
+    ast_string_field *__p__ = (ast_string_field *) (ptr);                                        \
+    ast_string_field target = *__p__;                                                            \
+    if (__dlen__ == 1) {                                                                         \
+        __ast_string_field_release_active(field_mgr_pool, *__p__);                               \
+        *__p__ = __ast_string_field_empty;                                                       \
+    } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) ||                              \
+           (!__ast_string_field_ptr_grow(&field_mgr, &field_mgr_pool, __dlen__, __p__)) ||       \
+           (target = __ast_string_field_alloc_space(&field_mgr, &field_mgr_pool, __dlen__))) {   \
+        if (target != (*__p__)) {                                                                \
+            __ast_string_field_release_active(field_mgr_pool, *__p__);                           \
+            *__p__ = target;                                                                     \
+        }                                                                                        \
+        memcpy(* (void **) __p__, __d__, __dlen__);                                              \
+    }                                                                                            \
     } while (0)
 
 /*!
index 2dd9c11fdf5861c9f813545c2e86050bcbdf31da..cdb23fc78ad8fd5dc563b4442f2d84f7f895c811 100644 (file)
@@ -1998,9 +1998,13 @@ void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
        for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
                if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
                        pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
-                       if ((pool->active == 0) && prev) {
-                               prev->prev = pool->prev;
-                               ast_free(pool);
+                       if (pool->active == 0) {
+                               if (prev) {
+                                       prev->prev = pool->prev;
+                                       ast_free(pool);
+                               } else {
+                                       pool->used = 0;
+                               }
                        }
                        break;
                }
@@ -2049,6 +2053,11 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
                /* Are we out of memory? */
                return;
        }
+       if (res == 0) {
+               __ast_string_field_release_active(*pool_head, *ptr);
+               *ptr = __ast_string_field_empty;
+               return;
+       }
        needed = (size_t)res + 1; /* NUL byte */
 
        if (needed > available) {