mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 00:58:12 +00:00
webrtcbin: Reject answers that don't contain the same number of m-line as offer
Otherwise, it segfaults later. Also add test to validate this. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2561>
This commit is contained in:
parent
56451b0f1a
commit
e26bd431ad
2 changed files with 116 additions and 9 deletions
|
@ -5396,18 +5396,16 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gint
|
||||||
check_transceivers_not_removed (GstWebRTCBin * webrtc,
|
transceivers_media_num_cmp (GstWebRTCBin * webrtc,
|
||||||
GstWebRTCSessionDescription * previous, GstWebRTCSessionDescription * new)
|
GstWebRTCSessionDescription * previous, GstWebRTCSessionDescription * new)
|
||||||
{
|
{
|
||||||
if (!previous)
|
if (!previous)
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
if (gst_sdp_message_medias_len (previous->sdp) >
|
return gst_sdp_message_medias_len (new->sdp) -
|
||||||
gst_sdp_message_medias_len (new->sdp))
|
gst_sdp_message_medias_len (previous->sdp);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -5495,6 +5493,35 @@ get_previous_description (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstWebRTCSessionDescription *
|
||||||
|
get_last_generated_description (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
|
GstWebRTCSDPType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GST_WEBRTC_SDP_TYPE_OFFER:
|
||||||
|
if (source == SDP_REMOTE)
|
||||||
|
return webrtc->priv->last_generated_answer;
|
||||||
|
else
|
||||||
|
return webrtc->priv->last_generated_offer;
|
||||||
|
break;
|
||||||
|
case GST_WEBRTC_SDP_TYPE_PRANSWER:
|
||||||
|
case GST_WEBRTC_SDP_TYPE_ANSWER:
|
||||||
|
if (source == SDP_LOCAL)
|
||||||
|
return webrtc->priv->last_generated_answer;
|
||||||
|
else
|
||||||
|
return webrtc->priv->last_generated_offer;
|
||||||
|
case GST_WEBRTC_SDP_TYPE_ROLLBACK:
|
||||||
|
return NULL;
|
||||||
|
default:
|
||||||
|
/* other values mean memory corruption/uninitialized! */
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* http://w3c.github.io/webrtc-pc/#set-description */
|
/* http://w3c.github.io/webrtc-pc/#set-description */
|
||||||
static GstStructure *
|
static GstStructure *
|
||||||
_set_description_task (GstWebRTCBin * webrtc, struct set_description *sd)
|
_set_description_task (GstWebRTCBin * webrtc, struct set_description *sd)
|
||||||
|
@ -5535,9 +5562,9 @@ _set_description_task (GstWebRTCBin * webrtc, struct set_description *sd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_transceivers_not_removed (webrtc,
|
if (transceivers_media_num_cmp (webrtc,
|
||||||
get_previous_description (webrtc, sd->source, sd->sdp->type),
|
get_previous_description (webrtc, sd->source, sd->sdp->type),
|
||||||
sd->sdp)) {
|
sd->sdp) < 0) {
|
||||||
g_set_error_literal (&error, GST_WEBRTC_ERROR,
|
g_set_error_literal (&error, GST_WEBRTC_ERROR,
|
||||||
GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||||
"m=lines removed from the SDP. Processing a completely new connection "
|
"m=lines removed from the SDP. Processing a completely new connection "
|
||||||
|
@ -5545,6 +5572,17 @@ _set_description_task (GstWebRTCBin * webrtc, struct set_description *sd)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((sd->sdp->type == GST_WEBRTC_SDP_TYPE_PRANSWER ||
|
||||||
|
sd->sdp->type == GST_WEBRTC_SDP_TYPE_ANSWER) &&
|
||||||
|
transceivers_media_num_cmp (webrtc,
|
||||||
|
get_last_generated_description (webrtc, sd->source, sd->sdp->type),
|
||||||
|
sd->sdp) != 0) {
|
||||||
|
g_set_error_literal (&error, GST_WEBRTC_ERROR,
|
||||||
|
GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||||
|
"Answer doesn't have the same number of m-lines as the offer.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!check_locked_mlines (webrtc, sd->sdp, &error))
|
if (!check_locked_mlines (webrtc, sd->sdp, &error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -4371,6 +4371,74 @@ GST_START_TEST (test_codec_preferences_in_on_new_transceiver)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_media_line (struct test_webrtc *t, GstElement * element,
|
||||||
|
GstWebRTCSessionDescription * desc, gpointer user_data)
|
||||||
|
{
|
||||||
|
GstSDPMedia *media = NULL;
|
||||||
|
const GstSDPMedia *existing_media;
|
||||||
|
GstSDPResult res;
|
||||||
|
|
||||||
|
existing_media = gst_sdp_message_get_media (desc->sdp, 0);
|
||||||
|
|
||||||
|
res = gst_sdp_media_copy (existing_media, &media);
|
||||||
|
fail_unless (res == GST_SDP_OK);
|
||||||
|
res = gst_sdp_message_add_media (desc->sdp, media);
|
||||||
|
fail_unless (res == GST_SDP_OK);
|
||||||
|
gst_sdp_media_free (media);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_answer_set_rejected (struct test_webrtc *t, GstElement * element,
|
||||||
|
GstPromise * promise, gpointer user_data)
|
||||||
|
{
|
||||||
|
const GstStructure *s;
|
||||||
|
GError *error = NULL;
|
||||||
|
GError *compare_error = user_data;
|
||||||
|
|
||||||
|
s = gst_promise_get_reply (promise);
|
||||||
|
fail_unless (s != NULL);
|
||||||
|
gst_structure_get (s, "error", G_TYPE_ERROR, &error, NULL);
|
||||||
|
fail_unless (g_error_matches (error, compare_error->domain,
|
||||||
|
compare_error->code));
|
||||||
|
fail_unless_equals_string (compare_error->message, error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_invalid_add_media_in_answer)
|
||||||
|
{
|
||||||
|
struct test_webrtc *t = create_audio_test ();
|
||||||
|
VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
|
||||||
|
NULL, NULL);
|
||||||
|
guint media_format_count[] = { 1 };
|
||||||
|
VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
|
||||||
|
media_format_count, &no_duplicate_payloads);
|
||||||
|
VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
|
||||||
|
&media_formats);
|
||||||
|
const gchar *expected_offer_setup[] = { "actpass", };
|
||||||
|
VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
|
||||||
|
const gchar *expected_offer_direction[] = { "sendrecv", };
|
||||||
|
VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
|
||||||
|
&offer_setup);
|
||||||
|
VAL_SDP_INIT (answer, add_media_line, NULL, NULL);
|
||||||
|
GError answer_set_error = { GST_WEBRTC_ERROR,
|
||||||
|
GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||||
|
(gchar *) "Answer doesn't have the same number of m-lines as the offer."
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Ensure that if the answer has more m-lines than the offer, it gets
|
||||||
|
* rejected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
t->on_answer_set = on_answer_set_rejected;
|
||||||
|
t->answer_set_data = &answer_set_error;
|
||||||
|
|
||||||
|
test_validate_sdp (t, &offer, &answer);
|
||||||
|
test_webrtc_free (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
webrtcbin_suite (void)
|
webrtcbin_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -4425,6 +4493,7 @@ webrtcbin_suite (void)
|
||||||
tcase_add_test (tc, test_codec_preferences_no_duplicate_extmaps);
|
tcase_add_test (tc, test_codec_preferences_no_duplicate_extmaps);
|
||||||
tcase_add_test (tc, test_codec_preferences_incompatible_extmaps);
|
tcase_add_test (tc, test_codec_preferences_incompatible_extmaps);
|
||||||
tcase_add_test (tc, test_codec_preferences_invalid_extmap);
|
tcase_add_test (tc, test_codec_preferences_invalid_extmap);
|
||||||
|
tcase_add_test (tc, test_invalid_add_media_in_answer);
|
||||||
if (sctpenc && sctpdec) {
|
if (sctpenc && sctpdec) {
|
||||||
tcase_add_test (tc, test_data_channel_create);
|
tcase_add_test (tc, test_data_channel_create);
|
||||||
tcase_add_test (tc, test_data_channel_remote_notify);
|
tcase_add_test (tc, test_data_channel_remote_notify);
|
||||||
|
|
Loading…
Reference in a new issue