1.1 --- a/ChangeLog
1.2 +++ b/ChangeLog
1.3 @@ -18,6 +18,10 @@
1.4 * Fix a leak when admitting UTF-8 text with a non-UTF-8 primary
1.5 encoding. (#14700)
1.6
1.7 + Jabber:
1.8 + * Fix crashes and memory leaks when receiving malformed voice
1.9 + and video requests. Thanks to Thijs Alkemade for reporting this!
1.10 +
1.11 Sametime:
1.12 * Separate "username" and "server" when adding new Sametime accounts.
1.13 (#14608)
2.1 --- a/libpurple/protocols/jabber/jingle/jingle.c
2.2 +++ b/libpurple/protocols/jabber/jingle/jingle.c
2.3 @@ -126,7 +126,7 @@
2.4 if (local_content != NULL) {
2.5 const gchar *senders = xmlnode_get_attrib(content, "senders");
2.6 gchar *local_senders = jingle_content_get_senders(local_content);
2.7 - if (strcmp(senders, local_senders))
2.8 + if (!purple_strequal(senders, local_senders))
2.9 jingle_content_modify(local_content, senders);
2.10 g_free(local_senders);
2.11 } else {
3.1 --- a/libpurple/protocols/jabber/jingle/rtp.c
3.2 +++ b/libpurple/protocols/jabber/jingle/rtp.c
3.3 @@ -590,6 +590,16 @@
3.4 senders = jingle_content_get_senders(content);
3.5 transport = jingle_content_get_transport(content);
3.6
3.7 + if (media_type == NULL) {
3.8 + g_free(name);
3.9 + g_free(remote_jid);
3.10 + g_free(senders);
3.11 + g_free(params);
3.12 + g_object_unref(transport);
3.13 + g_object_unref(session);
3.14 + return FALSE;
3.15 + }
3.16 +
3.17 if (JINGLE_IS_RAWUDP(transport))
3.18 transmitter = "rawudp";
3.19 else if (JINGLE_IS_ICEUDP(transport))
3.20 @@ -598,17 +608,17 @@
3.21 transmitter = "notransmitter";
3.22 g_object_unref(transport);
3.23
3.24 - is_audio = !strcmp(media_type, "audio");
3.25 + is_audio = g_str_equal(media_type, "audio");
3.26
3.27 - if (!strcmp(senders, "both"))
3.28 - type = is_audio == TRUE ? PURPLE_MEDIA_AUDIO
3.29 + if (purple_strequal(senders, "both"))
3.30 + type = is_audio ? PURPLE_MEDIA_AUDIO
3.31 : PURPLE_MEDIA_VIDEO;
3.32 - else if ((strcmp(senders, "initiator") == 0) ==
3.33 + else if (purple_strequal(senders, "initiator") ==
3.34 jingle_session_is_initiator(session))
3.35 - type = is_audio == TRUE ? PURPLE_MEDIA_SEND_AUDIO
3.36 + type = is_audio ? PURPLE_MEDIA_SEND_AUDIO
3.37 : PURPLE_MEDIA_SEND_VIDEO;
3.38 else
3.39 - type = is_audio == TRUE ? PURPLE_MEDIA_RECV_AUDIO
3.40 + type = is_audio ? PURPLE_MEDIA_RECV_AUDIO
3.41 : PURPLE_MEDIA_RECV_VIDEO;
3.42
3.43 params =
3.44 @@ -616,7 +626,17 @@
3.45 NULL, NULL, &num_params);
3.46
3.47 creator = jingle_content_get_creator(content);
3.48 - if (!strcmp(creator, "initiator"))
3.49 + if (creator == NULL) {
3.50 + g_free(name);
3.51 + g_free(media_type);
3.52 + g_free(remote_jid);
3.53 + g_free(senders);
3.54 + g_free(params);
3.55 + g_object_unref(session);
3.56 + return FALSE;
3.57 + }
3.58 +
3.59 + if (g_str_equal(creator, "initiator"))
3.60 is_creator = jingle_session_is_initiator(session);
3.61 else
3.62 is_creator = !jingle_session_is_initiator(session);
3.63 @@ -625,6 +645,8 @@
3.64 if(!purple_media_add_stream(media, name, remote_jid,
3.65 type, is_creator, transmitter, num_params, params)) {
3.66 purple_media_end(media, NULL, NULL);
3.67 + /* TODO: How much clean-up is necessary here? (does calling
3.68 + purple_media_end lead to cleaning up Jingle structs?) */
3.69 return FALSE;
3.70 }
3.71
3.72 @@ -646,9 +668,22 @@
3.73 const char *encoding_name,*id, *clock_rate;
3.74 PurpleMediaCodec *codec;
3.75 const gchar *media = xmlnode_get_attrib(description, "media");
3.76 - PurpleMediaSessionType type =
3.77 - !strcmp(media, "video") ? PURPLE_MEDIA_VIDEO :
3.78 - !strcmp(media, "audio") ? PURPLE_MEDIA_AUDIO : 0;
3.79 + PurpleMediaSessionType type;
3.80 +
3.81 + if (media == NULL) {
3.82 + purple_debug_warning("jingle-rtp", "missing media type\n");
3.83 + return NULL;
3.84 + }
3.85 +
3.86 + if (g_str_equal(media, "video")) {
3.87 + type = PURPLE_MEDIA_VIDEO;
3.88 + } else if (g_str_equal(media, "audio")) {
3.89 + type = PURPLE_MEDIA_AUDIO;
3.90 + } else {
3.91 + purple_debug_warning("jingle-rtp", "unknown media type: %s\n",
3.92 + media);
3.93 + return NULL;
3.94 + }
3.95
3.96 for (codec_element = xmlnode_get_child(description, "payload-type") ;
3.97 codec_element ;
3.98 @@ -769,19 +804,19 @@
3.99 switch (action) {
3.100 case JINGLE_SESSION_ACCEPT:
3.101 case JINGLE_SESSION_INITIATE: {
3.102 - JingleSession *session = jingle_content_get_session(content);
3.103 - JingleTransport *transport = jingle_transport_parse(
3.104 - xmlnode_get_child(xmlcontent, "transport"));
3.105 - xmlnode *description = xmlnode_get_child(xmlcontent, "description");
3.106 - GList *candidates = jingle_rtp_transport_to_candidates(transport);
3.107 - GList *codecs = jingle_rtp_parse_codecs(description);
3.108 - gchar *name = jingle_content_get_name(content);
3.109 - gchar *remote_jid =
3.110 - jingle_session_get_remote_jid(session);
3.111 + JingleSession *session;
3.112 + JingleTransport *transport;
3.113 + xmlnode *description;
3.114 + GList *candidates;
3.115 + GList *codecs;
3.116 + gchar *name;
3.117 + gchar *remote_jid;
3.118 PurpleMedia *media;
3.119
3.120 + session = jingle_content_get_session(content);
3.121 +
3.122 if (action == JINGLE_SESSION_INITIATE &&
3.123 - jingle_rtp_init_media(content) == FALSE) {
3.124 + !jingle_rtp_init_media(content)) {
3.125 /* XXX: send error */
3.126 jabber_iq_send(jingle_session_terminate_packet(
3.127 session, "general-error"));
3.128 @@ -789,6 +824,14 @@
3.129 break;
3.130 }
3.131
3.132 + transport = jingle_transport_parse(
3.133 + xmlnode_get_child(xmlcontent, "transport"));
3.134 + description = xmlnode_get_child(xmlcontent, "description");
3.135 + candidates = jingle_rtp_transport_to_candidates(transport);
3.136 + codecs = jingle_rtp_parse_codecs(description);
3.137 + name = jingle_content_get_name(content);
3.138 + remote_jid = jingle_session_get_remote_jid(session);
3.139 +
3.140 media = jingle_rtp_get_media(session);
3.141 purple_media_set_remote_codecs(media,
3.142 name, remote_jid, codecs);
4.1 --- a/libpurple/protocols/jabber/jingle/session.c
4.2 +++ b/libpurple/protocols/jabber/jingle/session.c
4.3 @@ -288,7 +288,7 @@
4.4 if (!js->sessions) {
4.5 purple_debug_info("jingle",
4.6 "Creating hash table for sessions\n");
4.7 - js->sessions = g_hash_table_new(g_str_hash, g_str_equal);
4.8 + js->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
4.9 }
4.10 purple_debug_info("jingle",
4.11 "inserting session with key: %s into table\n", sid);
4.12 @@ -411,26 +411,24 @@
4.13 xmlnode_new("jingle");
4.14 gchar *local_jid = jingle_session_get_local_jid(session);
4.15 gchar *remote_jid = jingle_session_get_remote_jid(session);
4.16 + gchar *sid = jingle_session_get_sid(session);
4.17
4.18 xmlnode_set_namespace(jingle, JINGLE);
4.19 xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
4.20
4.21 if (jingle_session_is_initiator(session)) {
4.22 - xmlnode_set_attrib(jingle, "initiator",
4.23 - jingle_session_get_local_jid(session));
4.24 - xmlnode_set_attrib(jingle, "responder",
4.25 - jingle_session_get_remote_jid(session));
4.26 + xmlnode_set_attrib(jingle, "initiator", local_jid);
4.27 + xmlnode_set_attrib(jingle, "responder", remote_jid);
4.28 } else {
4.29 - xmlnode_set_attrib(jingle, "initiator",
4.30 - jingle_session_get_remote_jid(session));
4.31 - xmlnode_set_attrib(jingle, "responder",
4.32 - jingle_session_get_local_jid(session));
4.33 + xmlnode_set_attrib(jingle, "initiator", remote_jid);
4.34 + xmlnode_set_attrib(jingle, "responder", local_jid);
4.35 }
4.36
4.37 + xmlnode_set_attrib(jingle, "sid", sid);
4.38 +
4.39 g_free(local_jid);
4.40 g_free(remote_jid);
4.41 -
4.42 - xmlnode_set_attrib(jingle, "sid", jingle_session_get_sid(session));
4.43 + g_free(sid);
4.44
4.45 return jingle;
4.46 }
4.47 @@ -508,11 +506,16 @@
4.48 JingleContent *
4.49 jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
4.50 {
4.51 - GList *iter = session->priv->contents;
4.52 + GList *iter;
4.53 +
4.54 + if (name == NULL)
4.55 + return NULL;
4.56 +
4.57 + iter = session->priv->contents;
4.58 for (; iter; iter = g_list_next(iter)) {
4.59 JingleContent *content = iter->data;
4.60 gchar *cname = jingle_content_get_name(content);
4.61 - gboolean result = !strcmp(name, cname);
4.62 + gboolean result = g_str_equal(name, cname);
4.63 g_free(cname);
4.64
4.65 if (creator != NULL) {
4.66 @@ -530,11 +533,16 @@
4.67 JingleContent *
4.68 jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
4.69 {
4.70 - GList *iter = session->priv->pending_contents;
4.71 + GList *iter;
4.72 +
4.73 + if (name == NULL)
4.74 + return NULL;
4.75 +
4.76 + iter = session->priv->pending_contents;
4.77 for (; iter; iter = g_list_next(iter)) {
4.78 JingleContent *content = iter->data;
4.79 gchar *cname = jingle_content_get_name(content);
4.80 - gboolean result = !strcmp(name, cname);
4.81 + gboolean result = g_str_equal(name, cname);
4.82 g_free(cname);
4.83
4.84 if (creator != NULL) {