From f7caf4e249af1f1cecf4d318c59e762597631811 Mon Sep 17 00:00:00 2001
From: Kinsey Moore <kmoore@digium.com>
Date: Mon, 28 Apr 2014 20:07:37 +0000
Subject: [PATCH] Bridging: Don't lock NULL bridges

When bridge locking was added for bridge snapshot creation, some
locations where bridge locking was added were not guaranteed to
actually have a bridge and locking NULL AO2 objects tends to cause
segfaults. This ensures that NULL bridges aren't locked.
........

Merged revisions 413073 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@413074 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 main/bridge.c       |  8 +++++--
 main/bridge_basic.c | 54 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/main/bridge.c b/main/bridge.c
index ee1e4a8e73..d06b7b5556 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -4072,9 +4072,13 @@ static void publish_blind_transfer(int is_external, enum ast_transfer_result res
 	struct ast_bridge_channel_pair pair;
 	pair.channel = transferer;
 	pair.bridge = bridge;
-	ast_bridge_lock(bridge);
+	if (bridge) {
+		ast_bridge_lock(bridge);
+	}
 	ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten);
-	ast_bridge_unlock(bridge);
+	if (bridge) {
+		ast_bridge_unlock(bridge);
+	}
 }
 
 enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 253aa35169..9a49b427bf 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -1534,11 +1534,23 @@ static void publish_transfer_success(struct attended_transfer_properties *props)
 		.bridge = props->target_bridge,
 	};
 
-	ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	if (transferee.bridge && transfer_target.bridge) {
+		ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	} else if (transferee.bridge) {
+		ast_bridge_lock(transferee.bridge);
+	} else if (transfer_target.bridge) {
+		ast_bridge_lock(transfer_target.bridge);
+	}
+
 	ast_bridge_publish_attended_transfer_bridge_merge(0, AST_BRIDGE_TRANSFER_SUCCESS,
 			&transferee, &transfer_target, props->transferee_bridge);
-	ast_bridge_unlock(transferee.bridge);
-	ast_bridge_unlock(transfer_target.bridge);
+
+	if (transferee.bridge) {
+		ast_bridge_unlock(transferee.bridge);
+	}
+	if (transfer_target.bridge) {
+		ast_bridge_unlock(transfer_target.bridge);
+	}
 }
 
 /*!
@@ -1559,11 +1571,23 @@ static void publish_transfer_threeway(struct attended_transfer_properties *props
 		.bridge = props->transferee_bridge,
 	};
 
-	ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	if (transferee.bridge && transfer_target.bridge) {
+		ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	} else if (transferee.bridge) {
+		ast_bridge_lock(transferee.bridge);
+	} else if (transfer_target.bridge) {
+		ast_bridge_lock(transfer_target.bridge);
+	}
+
 	ast_bridge_publish_attended_transfer_threeway(0, AST_BRIDGE_TRANSFER_SUCCESS,
 			&transferee, &transfer_target, &threeway);
-	ast_bridge_unlock(transferee.bridge);
-	ast_bridge_unlock(transfer_target.bridge);
+
+	if (transferee.bridge) {
+		ast_bridge_unlock(transferee.bridge);
+	}
+	if (transfer_target.bridge) {
+		ast_bridge_unlock(transfer_target.bridge);
+	}
 }
 
 /*!
@@ -1580,11 +1604,23 @@ static void publish_transfer_fail(struct attended_transfer_properties *props)
 		.bridge = props->target_bridge,
 	};
 
-	ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	if (transferee.bridge && transfer_target.bridge) {
+		ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
+	} else if (transferee.bridge) {
+		ast_bridge_lock(transferee.bridge);
+	} else if (transfer_target.bridge) {
+		ast_bridge_lock(transfer_target.bridge);
+	}
+
 	ast_bridge_publish_attended_transfer_fail(0, AST_BRIDGE_TRANSFER_FAIL,
 			&transferee, &transfer_target);
-	ast_bridge_unlock(transferee.bridge);
-	ast_bridge_unlock(transfer_target.bridge);
+
+	if (transferee.bridge) {
+		ast_bridge_unlock(transferee.bridge);
+	}
+	if (transfer_target.bridge) {
+		ast_bridge_unlock(transfer_target.bridge);
+	}
 }
 
 /*!
-- 
GitLab