summaryrefslogtreecommitdiff
path: root/subprojects
diff options
context:
space:
mode:
authorPhilippe Normand <philn@igalia.com>2023-03-12 14:55:22 +0000
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>2023-05-08 19:20:22 +0000
commitb75114983e85cef70da398c985e8ee7f8f68e3a1 (patch)
treee32d65efe3e90546b4fa3d8bf4e2130e14305b0c /subprojects
parentf9c24cd7e70c8b8e50a6b8df87623a009c37c7ec (diff)
downloadgstreamer-b75114983e85cef70da398c985e8ee7f8f68e3a1.tar.gz
webrtcdatachannel: Bind to parent webrtcbin using a weak reference
The previous approach of using a simple pointer could lead to a use-after-free in case a data-channel was created and its parent webrtcbin was disposed soon after. Fixes #2103 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4160>
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c4
-rw-r--r--subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c25
-rw-r--r--subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.h6
3 files changed, 30 insertions, 5 deletions
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
index 4f327c5858..4e9cd2e7f5 100644
--- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
+++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
@@ -2544,7 +2544,7 @@ _on_sctpdec_pad_added (GstElement * sctpdec, GstPad * pad,
if (!channel) {
channel = g_object_new (WEBRTC_TYPE_DATA_CHANNEL, NULL);
channel->parent.id = stream_id;
- channel->webrtcbin = webrtc;
+ webrtc_data_channel_set_webrtcbin (channel, webrtc);
g_signal_emit (webrtc, gst_webrtc_bin_signals[PREPARE_DATA_CHANNEL_SIGNAL],
0, channel, FALSE);
@@ -7196,7 +7196,7 @@ gst_webrtc_bin_create_data_channel (GstWebRTCBin * webrtc, const gchar * label,
gst_element_sync_state_with_parent (ret->sink_bin);
ret = gst_object_ref (ret);
- ret->webrtcbin = webrtc;
+ webrtc_data_channel_set_webrtcbin (ret, webrtc);
g_ptr_array_add (webrtc->priv->data_channels, ret);
DC_UNLOCK (webrtc);
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c
index 8c9c59a829..1305c740ac 100644
--- a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c
+++ b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.c
@@ -51,6 +51,7 @@ typedef void (*ChannelTask) (GstWebRTCDataChannel * channel,
struct task
{
+ GstWebRTCBin *webrtcbin;
GstWebRTCDataChannel *channel;
ChannelTask func;
gpointer user_data;
@@ -69,6 +70,7 @@ _execute_task (GstWebRTCBin * webrtc, struct task *task)
static void
_free_task (struct task *task)
{
+ g_object_unref (task->webrtcbin);
gst_object_unref (task->channel);
if (task->notify)
@@ -80,14 +82,22 @@ static void
_channel_enqueue_task (WebRTCDataChannel * channel, ChannelTask func,
gpointer user_data, GDestroyNotify notify)
{
- struct task *task = g_new0 (struct task, 1);
+ GstWebRTCBin *webrtcbin = NULL;
+ struct task *task = NULL;
+ webrtcbin = g_weak_ref_get (&channel->webrtcbin_weak);
+ if (!webrtcbin)
+ return;
+
+ task = g_new0 (struct task, 1);
+
+ task->webrtcbin = webrtcbin;
task->channel = gst_object_ref (channel);
task->func = func;
task->user_data = user_data;
task->notify = notify;
- gst_webrtc_bin_enqueue_task (channel->webrtcbin,
+ gst_webrtc_bin_enqueue_task (task->webrtcbin,
(GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task,
NULL);
}
@@ -1139,6 +1149,8 @@ gst_webrtc_data_channel_finalize (GObject * object)
g_clear_object (&channel->appsrc);
g_clear_object (&channel->appsink);
+ g_weak_ref_clear (&channel->webrtcbin_weak);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -1164,6 +1176,8 @@ webrtc_data_channel_init (WebRTCDataChannel * channel)
G_LOCK (outstanding_channels_lock);
outstanding_channels = g_list_prepend (outstanding_channels, channel);
G_UNLOCK (outstanding_channels_lock);
+
+ g_weak_ref_init (&channel->webrtcbin_weak, NULL);
}
static void
@@ -1213,3 +1227,10 @@ webrtc_data_channel_link_to_sctp (WebRTCDataChannel * channel,
}
}
}
+
+void
+webrtc_data_channel_set_webrtcbin (WebRTCDataChannel * channel,
+ GstWebRTCBin * webrtcbin)
+{
+ g_weak_ref_set (&channel->webrtcbin_weak, webrtcbin);
+}
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.h b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.h
index dd65a66ae3..919949f682 100644
--- a/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.h
+++ b/subprojects/gst-plugins-bad/ext/webrtc/webrtcdatachannel.h
@@ -51,7 +51,7 @@ struct _WebRTCDataChannel
GstElement *sink_bin;
GstElement *appsink;
- GstWebRTCBin *webrtcbin;
+ GWeakRef webrtcbin_weak;
gboolean opened;
gulong src_probe;
GError *stored_error;
@@ -72,6 +72,10 @@ G_GNUC_INTERNAL
void webrtc_data_channel_link_to_sctp (WebRTCDataChannel *channel,
WebRTCSCTPTransport *sctp_transport);
+G_GNUC_INTERNAL
+void webrtc_data_channel_set_webrtcbin (WebRTCDataChannel *channel,
+ GstWebRTCBin *webrtcbin);
+
G_DECLARE_FINAL_TYPE (WebRTCErrorIgnoreBin, webrtc_error_ignore_bin, WEBRTC, ERROR_IGNORE_BIN, GstBin);
G_END_DECLS