Fix potential bridge hook resource leak if the hook install fails.
authorRichard Mudgett <rmudgett@digium.com>
Thu, 20 Jun 2013 17:21:40 +0000 (17:21 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Thu, 20 Jun 2013 17:21:40 +0000 (17:21 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392335 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/confbridge/conf_config_parser.c
include/asterisk/bridging_features.h
main/bridging.c
main/features.c
res/parking/parking_bridge_features.c

index 042968c..35d96ae 100644 (file)
@@ -2161,8 +2161,10 @@ int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user)
                ao2_ref(menu, +1);
                pvt->menu = menu;
 
-               ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf, menu_hook_callback,
-                       pvt, menu_hook_destroy, 0);
+               if (ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf,
+                       menu_hook_callback, pvt, menu_hook_destroy, 0)) {
+                       menu_hook_destroy(pvt);
+               }
        }
 
        ao2_unlock(menu);
index 1ee13a4..6399a22 100644 (file)
@@ -390,7 +390,7 @@ int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval);
  * \param remove_flags Dictates what situations the hook should be removed.
  *
  * \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
  *
  * Example usage:
  *
@@ -420,7 +420,7 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
  * \param remove_flags Dictates what situations the hook should be removed.
  *
  * \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
  *
  * Example usage:
  *
@@ -450,7 +450,7 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
  * \param remove_flags Dictates what situations the hook should be removed.
  *
  * \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
  *
  * Example usage:
  *
@@ -481,7 +481,7 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
  * \param remove_flags Dictates what situations the hook should be removed.
  *
  * \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
  *
  * Example usage:
  *
@@ -503,7 +503,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
        enum ast_bridge_hook_remove_flags remove_flags);
 
 /*!
- * \brief attach an interval hook to a bridge features structure
+ * \brief Attach an interval hook to a bridge features structure
  *
  * \param features Bridge features structure
  * \param interval The interval that the hook should execute at in milliseconds
@@ -513,7 +513,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
  * \param remove_flags Dictates what situations the hook should be removed.
  *
  * \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
  *
  * \code
  * struct ast_bridge_features features;
index ad730f9..5101237 100644 (file)
@@ -4893,6 +4893,15 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
 
        /* Once done we put it in the container. */
        res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
+       if (res) {
+               /*
+                * Could not link the hook into the container.
+                *
+                * Remove the hook_pvt destructor call from the hook since we
+                * are returning failure to install the hook.
+                */
+               hook->destructor = NULL;
+       }
        ao2_ref(hook, -1);
 
        return res;
@@ -4916,6 +4925,15 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
 
        /* Once done we put it in the container. */
        res = ao2_link(features->hangup_hooks, hook) ? 0 : -1;
+       if (res) {
+               /*
+                * Could not link the hook into the container.
+                *
+                * Remove the hook_pvt destructor call from the hook since we
+                * are returning failure to install the hook.
+                */
+               hook->destructor = NULL;
+       }
        ao2_ref(hook, -1);
 
        return res;
@@ -4939,6 +4957,15 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
 
        /* Once done we put it in the container. */
        res = ao2_link(features->join_hooks, hook) ? 0 : -1;
+       if (res) {
+               /*
+                * Could not link the hook into the container.
+                *
+                * Remove the hook_pvt destructor call from the hook since we
+                * are returning failure to install the hook.
+                */
+               hook->destructor = NULL;
+       }
        ao2_ref(hook, -1);
 
        return res;
@@ -4962,6 +4989,15 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
 
        /* Once done we put it in the container. */
        res = ao2_link(features->leave_hooks, hook) ? 0 : -1;
+       if (res) {
+               /*
+                * Could not link the hook into the container.
+                *
+                * Remove the hook_pvt destructor call from the hook since we
+                * are returning failure to install the hook.
+                */
+               hook->destructor = NULL;
+       }
        ao2_ref(hook, -1);
 
        return res;
@@ -5013,11 +5049,17 @@ int ast_bridge_interval_hook(struct ast_bridge_features *features,
                hook, hook->parms.timer.interval, features);
        ast_heap_wrlock(features->interval_hooks);
        res = ast_heap_push(features->interval_hooks, hook);
+       ast_heap_unlock(features->interval_hooks);
        if (res) {
-               /* Could not push the hook onto the heap. */
+               /*
+                * Could not push the hook into the heap
+                *
+                * Remove the hook_pvt destructor call from the hook since we
+                * are returning failure to install the hook.
+                */
+               hook->destructor = NULL;
                ao2_ref(hook, -1);
        }
-       ast_heap_unlock(features->interval_hooks);
 
        return res ? -1 : 0;
 }
index c44520c..ff68b06 100644 (file)
@@ -3415,6 +3415,7 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
        size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
        size_t len_feature = strlen(feature_name) + 1;
        size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
+       int res;
 
        /* Fill in application run hook data. */
        hook_data = ast_malloc(len_data);
@@ -3434,8 +3435,12 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
        }
        strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
 
-       return ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
+       res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
                ast_free_ptr, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
+       if (res) {
+               ast_free(hook_data);
+       }
+       return res;
 }
 
 static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags)
index 8e5d739..3c01207 100644 (file)
@@ -542,6 +542,7 @@ void parking_set_duration(struct ast_bridge_features *features, struct parked_us
        if (ast_bridge_interval_hook(features, time_limit,
                parking_duration_callback, user, parking_duration_cb_destroyer, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
                ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n");
+               ao2_ref(user, -1);
        }
 }