Fix crashes and memory leaks when receiving malformed voice release-2.x.y
authorMark Doliner <markdoliner@pidgin.im>
Tue, 06 Dec 2011 07:06:01 +0000
branchrelease-2.x.y
changeset15eb0e242206 pushlog
parent 883a1b407408
child 4fff920c6493
Fix crashes and memory leaks when receiving malformed voice
and video requests. Thanks to Thijs Alkemade for reporting this!
ChangeLog
libpurple/protocols/jabber/jingle/jingle.c
libpurple/protocols/jabber/jingle/rtp.c
libpurple/protocols/jabber/jingle/session.c
      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) {