pidgin
Attached is a patch to fix all known security issues in pidgin in
Wheezy-LTS.
I found that a number of ther CVEs under security-tracker.debian.org
referenced the patch for the fix for the wrong CVE, so I had to retrieve
the correct patches from upstream git.
I also found that the security fix I identified for CVE-2016-2372 was
the same as one of the patches for CVE-2016-2369 so I didn't apply it
twice.
Still need to test this and make a copy for testing.
--
Brian May <brian@linuxpenguins.xyz>
https://linuxpenguins.xyz/brian/
diff -Nru pidgin-2.10.10/debian/changelog pidgin-2.10.10/debian/changelog
--- pidgin-2.10.10/debian/changelog 2014-10-20 06:54:23.000000000 +1100
+++ pidgin-2.10.10/debian/changelog 2016-06-28 06:57:33.000000000 +1000
@@ -1,3 +1,29 @@
+pidgin (2.10.10-1~deb7u2) wheezy-security; urgency=high
+
+ * Non-maintainer upload by the Security Team.
+ * CVE-2016-2365: Fix TALOS-CAN-0133
+ * CVE-2016-2366: Fix TALOS-CAN-0134
+ * CVE-2016-2367-1.patch: Fix chunk decoding errors (TALOS-2016-0135)
+ * CVE-2016-2367-2.patch: Check the chunk header (TALOS-2016-0135)
+ * CVE-2016-2367-3.patch: Add a check to make sure the file can have a chunk
+ (TALOS-2016-0135)
+ * CVE-2016-2368-1.patch: Fix for TALOS-CAN-0136 part 1
+ * CVE-2016-2368-2.patch: Fix for TALOS-CAN-0136 part 2
+ * CVE-2016-2369.patch: Fix for TALOS-CAN-0137
+ * CVE-2016-2370.patch: Fix for TALOS-CAN-0138
+ * CVE-2016-2371.patch: Fix TALOS-CAN-0139
+ * CVE-2016-2372/TALOS-2016-0140: Fixed by CVE-2016-2367-2.patch
+ * CVE-2016-2373.patch: Fix TALOS-CAN-0141
+ * CVE-2016-2374.patch: Fix for TALOS-CAN-0142
+ * CVE-2016-2375.patch: Fix for TALOS-CAN-0143
+ * CVE-2016-2376.patch: Fix TALOS-CAN-0118
+ * CVE-2016-2377.patch: TALOS-CAN-0119
+ * CVE-2016-2378.patch: Fix for TALOS-CAN-0120
+ * CVE-2016-2380.patch: Fix for TALOS-CAN-0123
+ * CVE-2016-4323.patch: Fix TALOS-CAN-0128
+
+ -- Brian May <bam@debian.org> Mon, 27 Jun 2016 19:05:23 +1000
+
pidgin (2.10.10-1~deb7u1) stable-security; urgency=low
* Build for stable-security
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2365.patch pidgin-2.10.10/debian/patches/CVE-2016-2365.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2365.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2365.patch 2016-06-27 18:55:11.000000000 +1000
@@ -0,0 +1,67 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464897231 18000
+# Branch release-2.x.y
+# Node ID 1c4acc6977a8686ad980e5b820327c9c47dbeaca
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0133
+
+--- a/libpurple/protocols/mxit/formcmds.c
++++ b/libpurple/protocols/mxit/formcmds.c
+@@ -395,6 +395,9 @@
+ /* validator */
+ validator = g_hash_table_lookup(hash, "v");
+
++ if (!name || !validator)
++ return;
++
+ /* image data */
+ tmp = g_hash_table_lookup(hash, "dat");
+ if (tmp) {
+@@ -430,13 +433,13 @@
+ }
+
+ tmp = g_hash_table_lookup(hash, "fw");
+- width = atoi(tmp);
++ width = (tmp ? atoi(tmp) : 0);
+
+ tmp = g_hash_table_lookup(hash, "fh");
+- height = atoi(tmp);
++ height = (tmp ? atoi(tmp) : 0);
+
+ tmp = g_hash_table_lookup(hash, "layer");
+- layer = atoi(tmp);
++ layer = (tmp ? atoi(tmp) : 0);
+
+ purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator);
+ }
+@@ -525,21 +528,26 @@
+
+ /* table name */
+ name = g_hash_table_lookup(hash, "nm");
++ if (!name)
++ return;
+
+ /* number of columns */
+ tmp = g_hash_table_lookup(hash, "col");
+- nr_columns = atoi(tmp);
++ nr_columns = (tmp ? atoi(tmp) : 0);
+
+ /* number of rows */
+ tmp = g_hash_table_lookup(hash, "row");
+- nr_rows = atoi(tmp);
++ nr_rows = (tmp ? atoi(tmp) : 0);
+
+ /* mode */
+ tmp = g_hash_table_lookup(hash, "mode");
+- mode = atoi(tmp);
++ mode = (tmp ? atoi(tmp) : 0);
+
+ /* table data */
+ tmp = g_hash_table_lookup(hash, "d");
++ if (!tmp)
++ tmp = "";
++
+ coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */
+
+ purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2366.patch pidgin-2.10.10/debian/patches/CVE-2016-2366.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2366.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2366.patch 2016-06-28 06:59:47.000000000 +1000
@@ -0,0 +1,44 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464891849 18000
+# Branch release-2.x.y
+# Node ID abdc3025f6b8b0dabb36bc84e994d6735e4abb3c
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0134
+
+--- a/libpurple/protocols/mxit/formcmds.c
++++ b/libpurple/protocols/mxit/formcmds.c
+@@ -522,9 +522,9 @@
+ const char* tmp;
+ const char* name;
+ int mode;
+- int nr_columns = 0, nr_rows = 0;
++ unsigned int nr_columns = 0, nr_rows = 0;
+ gchar** coldata;
+- int i, j;
++ unsigned int i, j;
+
+ /* table name */
+ name = g_hash_table_lookup(hash, "nm");
+@@ -550,6 +550,12 @@
+
+ coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */
+
++ if (g_strv_length(coldata) != (nr_rows * nr_columns)) {
++ purple_debug_info(MXIT_PLUGIN_ID, "Invalid table data: cols=%i rows=%i\n", nr_columns, nr_rows);
++ g_strfreev(coldata);
++ return;
++ }
++
+ purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
+
+ for (i = 0; i < nr_rows; i++) {
+@@ -557,6 +563,8 @@
+ purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]);
+ }
+ }
++
++ g_strfreev(coldata);
+ }
+
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2367-1.patch pidgin-2.10.10/debian/patches/CVE-2016-2367-1.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2367-1.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2367-1.patch 2016-06-27 18:04:38.000000000 +1000
@@ -0,0 +1,330 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464975230 18000
+# Branch release-2.x.y
+# Node ID 5e3601f8bde493d648916b611c2f81d507fcc9da
+# Parent ae243a809727b89e75be02a4e4b371089feac546
+Fix chunk decoding errors
+
+--- a/libpurple/protocols/mxit/chunk.c
++++ b/libpurple/protocols/mxit/chunk.c
+@@ -449,13 +449,16 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param offer Decoded offerfile information
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-void mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
++gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
+ {
+ int pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen );
+
++ memset( offer, 0, sizeof( struct offerfile_chunk ) );
++
+ /* id [8 bytes] */
+ pos += get_data( &chunkdata[pos], offer->fileid, 8);
+
+@@ -483,6 +486,8 @@
+
+ /* flags [4 bytes] */
+ /* not used by libPurple */
++
++ return TRUE;
+ }
+
+
+@@ -492,13 +497,16 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param offer Decoded getfile information
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-void mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
++gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
+ {
+ int pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen );
+
++ memset( getfile, 0, sizeof( struct getfile_chunk ) );
++
+ /* id [8 bytes] */
+ pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+
+@@ -513,6 +521,8 @@
+
+ /* file data */
+ getfile->data = &chunkdata[pos];
++
++ return TRUE;
+ }
+
+
+@@ -522,13 +532,16 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param splash Decoded splash image information
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-static void mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
++gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
+ {
+ int pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen );
+
++ memset( splash, 0, sizeof( struct splash_chunk ) );
++
+ /* anchor [1 byte] */
+ pos += get_int8( &chunkdata[pos], &(splash->anchor) );
+
+@@ -543,6 +556,8 @@
+
+ /* data length */
+ splash->datalen = datalen - pos;
++
++ return TRUE;
+ }
+
+
+@@ -552,14 +567,17 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param offer Decoded custom resource
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-void mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
++gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
+ {
+ int pos = 0;
+ unsigned int chunklen = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen );
+
++ memset( cr, 0, sizeof( struct cr_chunk ) );
++
+ /* id [UTF-8] */
+ pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
+
+@@ -584,9 +602,10 @@
+ {
+ struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
+
+- mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash );
+-
+- cr->resources = g_list_append( cr->resources, splash );
++ if ( mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash ) )
++ cr->resources = g_list_append( cr->resources, splash );
++ else
++ g_free( splash );
+ break;
+ }
+ case CP_CHUNK_CLICK : /* splash click */
+@@ -604,6 +623,8 @@
+ pos += chunk_length( chunk );
+ chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) );
+ }
++
++ return TRUE;
+ }
+
+
+@@ -613,19 +634,22 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param sendfile Decoded sendfile information
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-void mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
++gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
+ {
+ int pos = 0;
+ unsigned short entries = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen );
+
++ memset( sendfile, 0, sizeof( struct sendfile_chunk ) );
++
+ /* number of entries [2 bytes] */
+ pos += get_int16( &chunkdata[pos], &entries );
+
+ if ( entries < 1 ) /* no data */
+- return;
++ return FALSE;
+
+ /* contactAddress [UTF-8 string] */
+ pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) );
+@@ -635,6 +659,8 @@
+
+ /* status message [UTF-8 string] */
+ pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
++
++ return TRUE;
+ }
+
+
+@@ -644,19 +670,22 @@
+ * @param chunkdata Chunked data buffer
+ * @param datalen The length of the chunked data
+ * @param avatar Decoded avatar information
++ * @return TRUE if successfully parsed, otherwise FALSE
+ */
+-void mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
++gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
+ {
+ int pos = 0;
+ unsigned int numfiles = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen );
+
++ memset( avatar, 0, sizeof( struct getavatar_chunk ) );
++
+ /* number of files [4 bytes] */
+ pos += get_int32( &chunkdata[pos], &numfiles );
+
+ if ( numfiles < 1 ) /* no data */
+- return;
++ return FALSE;
+
+ /* mxitId [UTF-8 string] */
+ pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) );
+@@ -684,4 +713,6 @@
+
+ /* file data */
+ avatar->data = &chunkdata[pos];
++
++ return TRUE;
+ }
+--- a/libpurple/protocols/mxit/chunk.h
++++ b/libpurple/protocols/mxit/chunk.h
+@@ -182,11 +182,12 @@
+ size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
+
+ /* Decode chunk */
+-void mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer );
+-void mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile );
+-void mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr );
+-void mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile );
+-void mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar );
++gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer );
++gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile );
++gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr );
++gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile );
++gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar );
++gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash );
+
+ #endif /* _MXIT_CHUNK_H_ */
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -2201,27 +2201,26 @@
+ struct cr_chunk chunk;
+
+ /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct cr_chunk ) );
+- mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
++ if ( mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
+
+- purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
++ purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+
+- /* this is a splash-screen operation */
+- if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
+- if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
+- struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
+- gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
+-
+- if ( splash != NULL )
+- splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
++ /* this is a splash-screen operation */
++ if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
++ if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
++ struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
++ gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
++
++ if ( splash != NULL )
++ splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
++ }
++ else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
++ splash_remove( session );
+ }
+- else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
+- splash_remove( session );
+- }
+-
+- /* cleanup custom resources */
+- g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
+
++ /* cleanup custom resources */
++ g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
++ }
+ }
+ break;
+
+@@ -2230,11 +2229,10 @@
+ struct offerfile_chunk chunk;
+
+ /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
+- mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* process the offer */
+- mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
++ if ( mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ /* process the offer */
++ mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
++ }
+ }
+ break;
+
+@@ -2243,11 +2241,10 @@
+ struct getfile_chunk chunk;
+
+ /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct getfile_chunk ) );
+- mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* process the getfile */
+- mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
++ if ( mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ /* process the getfile */
++ mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
++ }
+ }
+ break;
+
+@@ -2257,11 +2254,8 @@
+ struct contact* contact = NULL;
+
+ /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
+- mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* update avatar image */
+- if ( chunk.data ) {
++ if ( mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ /* update avatar image */
+ purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
+
+ contact = get_mxit_invite_contact( session, chunk.mxitid );
+@@ -2288,13 +2282,12 @@
+ {
+ struct sendfile_chunk chunk;
+
+- memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
+- mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
++ if ( mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+
+- purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+-
+- if ( chunk.status != 0 ) /* not success */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
++ if ( chunk.status != 0 ) /* not success */
++ mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
++ }
+ }
+ break;
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2367-2.patch pidgin-2.10.10/debian/patches/CVE-2016-2367-2.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2367-2.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2367-2.patch 2016-06-27 18:04:50.000000000 +1000
@@ -0,0 +1,168 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464975572 18000
+# Branch release-2.x.y
+# Node ID 1c5197a66760396a28de87d566e0eb0d986175ea
+# Parent 5e3601f8bde493d648916b611c2f81d507fcc9da
+Check the chunk header
+
+--- a/libpurple/protocols/mxit/chunk.h
++++ b/libpurple/protocols/mxit/chunk.h
+@@ -85,7 +85,7 @@
+ static inline guint32 chunk_length( gchar* chunkheader )
+ {
+ guint32 length = *( (const guint32*) &chunkheader[1] );
+- return htonl( length );
++ return ntohl( length );
+ }
+
+ static inline void set_chunk_length( gchar* chunkheader, guint32 size )
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -2163,21 +2163,6 @@
+
+
+ /*------------------------------------------------------------------------
+- * Return the length of a multimedia chunk
+- *
+- * @return The actual chunk data length in bytes
+- */
+-static int get_chunk_len( const char* chunkdata )
+-{
+- int* sizeptr;
+-
+- sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */
+-
+- return ntohl( *sizeptr );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+ * Process a received multimedia packet.
+ *
+ * @param session The MXit session object
+@@ -2186,22 +2171,33 @@
+ */
+ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
+ {
+- char type;
+- int size;
++ guint chunktype;
++ guint32 chunksize;
++ gchar* chunkdata;
++
++ /* received packet is too short to even contain a chunk header */
++ if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE )
++ return;
++
++ /* decode the chunk header */
++ chunktype = chunk_type( records[0]->fields[0]->data );
++ chunksize = chunk_length( records[0]->fields[0]->data );
++ chunkdata = chunk_data( records[0]->fields[0]->data );
++
++ /* check chunk size against length of received data */
++ if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len )
++ return;
+
+- type = records[0]->fields[0]->data[0];
+- size = get_chunk_len( records[0]->fields[0]->data );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize );
+
+ /* supported chunked data types */
+- switch ( type ) {
++ switch ( chunktype ) {
+ case CP_CHUNK_CUSTOM : /* custom resource */
+ {
+ struct cr_chunk chunk;
+
+ /* decode the chunked data */
+- if ( mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ if ( mxit_chunk_parse_cr( chunkdata, chunksize, &chunk ) ) {
+
+ purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+
+@@ -2229,7 +2225,7 @@
+ struct offerfile_chunk chunk;
+
+ /* decode the chunked data */
+- if ( mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ if ( mxit_chunk_parse_offer( chunkdata, chunksize, &chunk ) ) {
+ /* process the offer */
+ mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+ }
+@@ -2241,7 +2237,7 @@
+ struct getfile_chunk chunk;
+
+ /* decode the chunked data */
+- if ( mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ if ( mxit_chunk_parse_get( chunkdata, chunksize, &chunk ) ) {
+ /* process the getfile */
+ mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+ }
+@@ -2254,7 +2250,7 @@
+ struct contact* contact = NULL;
+
+ /* decode the chunked data */
+- if ( mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) {
+ /* update avatar image */
+ purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
+
+@@ -2277,12 +2273,16 @@
+ /* this is a reply packet to a set avatar request. no action is required */
+ break;
+
++ case CP_CHUNK_REJECT :
++ /* this is a reply packet to a reject file request. no action is required */
++ break;
++
+ case CP_CHUNK_DIRECT_SND :
+ /* this is a ack for a file send. */
+ {
+ struct sendfile_chunk chunk;
+
+- if ( mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ) ) {
++ if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &chunk ) ) {
+ purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+
+ if ( chunk.status != 0 ) /* not success */
+@@ -2296,7 +2296,7 @@
+ break;
+
+ default :
+- purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
++ purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype );
+ break;
+ }
+ }
+@@ -2612,7 +2612,7 @@
+
+ for ( j = 0; j < r->fcount; j++ ) {
+ f = r->fields[j];
+- purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
++ purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data );
+ }
+ }
+ }
+@@ -2734,7 +2734,7 @@
+ field->data = &session->rx_dbuf[i + 1];
+ field->len = session->rx_i - i;
+ /* now skip the binary data */
+- res = get_chunk_len( field->data );
++ res = chunk_length( field->data );
+ /* determine if we have more packets */
+ if ( res + 6 + i < session->rx_i ) {
+ /* we have more than one packet in this stream */
+--- a/libpurple/protocols/mxit/protocol.h
++++ b/libpurple/protocols/mxit/protocol.h
+@@ -241,7 +241,7 @@
+
+ struct field {
+ char* data;
+- int len;
++ size_t len;
+ };
+
+ struct record {
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2367-3.patch pidgin-2.10.10/debian/patches/CVE-2016-2367-3.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2367-3.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2367-3.patch 2016-06-27 18:05:02.000000000 +1000
@@ -0,0 +1,21 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464975625 18000
+# Branch release-2.x.y
+# Node ID 648f667a679cf13ba957e6481edafa7e210faaf3
+# Parent 1c5197a66760396a28de87d566e0eb0d986175ea
+Add a check to make sure the file can have a chunk
+
+--- a/libpurple/protocols/mxit/chunk.c
++++ b/libpurple/protocols/mxit/chunk.c
+@@ -507,6 +507,10 @@
+
+ memset( getfile, 0, sizeof( struct getfile_chunk ) );
+
++ /* ensure that the chunk size is atleast the minimum size for a "get file" chunk */
++ if ( datalen < 20 )
++ return FALSE;
++
+ /* id [8 bytes] */
+ pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2368-1.patch pidgin-2.10.10/debian/patches/CVE-2016-2368-1.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2368-1.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2368-1.patch 2016-06-24 18:42:14.000000000 +1000
@@ -0,0 +1,119 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464976622 18000
+# Branch release-2.x.y
+# Node ID 60f95045db42687aca293429a4bbafe2ef537270
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0136 part 1
+
+--- a/libpurple/protocols/mxit/http.c
++++ b/libpurple/protocols/mxit/http.c
+@@ -63,9 +63,9 @@
+ * @param pktlen The length of the packet data
+ * @return Return -1 on error, otherwise 0
+ */
+-static int mxit_http_raw_write( int fd, const char* pktdata, int pktlen )
++static int mxit_http_raw_write( int fd, const char* pktdata, size_t pktlen )
+ {
+- int written;
++ size_t written;
+ int res;
+
+ written = 0;
+@@ -315,22 +315,25 @@
+ * @param session The MXit session object
+ * @param host The server name to connect to
+ * @param port The port number to connect to
+- * @param data The HTTP request data (including HTTP headers etc.)
++ * @param header The HTTP header.
++ * @param data The HTTP request data.
+ * @param datalen The HTTP request data length
+ */
+-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen )
++void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen )
+ {
+ PurpleProxyConnectData* con = NULL;
+ struct http_request* req;
++ size_t headerlen = strlen( header );
+
+ /* build the http request */
+ req = g_new0( struct http_request, 1 );
+ req->session = session;
+ req->host = host;
+ req->port = port;
+- req->data = g_malloc0( datalen );
+- memcpy( req->data, data, datalen );
+- req->datalen = datalen;
++ req->data = g_malloc0( headerlen + datalen );
++ memcpy( req->data, header, headerlen );
++ memcpy( req->data + headerlen, data, datalen );
++ req->datalen = headerlen + datalen;
+
+ /* open connection to the HTTP server */
+ con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
+--- a/libpurple/protocols/mxit/http.h
++++ b/libpurple/protocols/mxit/http.h
+@@ -35,11 +35,11 @@
+ char* host;
+ int port;
+ char* data;
+- int datalen;
++ size_t datalen;
+ };
+
+
+-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen );
++void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen );
+
+
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -335,11 +335,10 @@
+ */
+ static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
+ {
+- char request[256 + packet->datalen];
+- int reqlen;
+ char* host_name;
+ int host_port;
+ gboolean ok;
++ gchar* httpheader;
+
+ /* extract the HTTP host name and host port number to connect to */
+ ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
+@@ -351,8 +350,8 @@
+ packet->header[packet->headerlen - 1] = '\0';
+ packet->headerlen--;
+
+- /* build the HTTP request packet */
+- reqlen = g_snprintf( request, 256,
++ /* build the HTTP request header */
++ httpheader = g_strdup_printf(
+ "POST %s?%s HTTP/1.1\r\n"
+ "User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
+ "Content-Type: application/octet-stream\r\n"
+@@ -365,17 +364,17 @@
+ packet->datalen - MXIT_MS_OFFSET
+ );
+
+- /* copy over the packet body data (could be binary) */
+- memcpy( request + reqlen, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
+- reqlen += packet->datalen;
+-
+ #ifdef DEBUG_PROTOCOL
+ purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
+- dump_bytes( session, request, reqlen );
++ dump_bytes( session, httpheader, strlen( httpheader ) );
++ dump_bytes( session, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
+ #endif
+
+ /* send the request to the HTTP server */
+- mxit_http_send_request( session, host_name, host_port, request, reqlen );
++ mxit_http_send_request( session, host_name, host_port, httpheader, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
++
++ /* cleanup */
++ g_free( httpheader );
+ }
+
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2368-2.patch pidgin-2.10.10/debian/patches/CVE-2016-2368-2.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2368-2.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2368-2.patch 2016-06-24 18:42:15.000000000 +1000
@@ -0,0 +1,363 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464976637 18000
+# Branch release-2.x.y
+# Node ID f6efc254e94741e3efa05faff081c157de987a55
+# Parent 60f95045db42687aca293429a4bbafe2ef537270
+Fix for TALOS-CAN-0136 part 2
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -149,6 +149,34 @@
+ }
+
+
++/*------------------------------------------------------------------------
++ * scnprintf
++ *
++ * @param string The destination buffer.
++ * @param size The maximum size of the destination buffer.
++ * @param format The format string
++ * @param ... The parameters to the format string.
++ * @return The number of characters actually stored in the buffer.
++ */
++static int scnprintf( gchar* string, size_t size, const char *format, ... )
++{
++ va_list args;
++ guint i;
++
++ va_start( args, format );
++ i = g_vsnprintf( string, size, format, args );
++ va_end( args );
++
++ if ( i < size )
++ return i;
++ else if ( size > 0 ) /* destination buffer too short - return number of characters actually inserted */
++ return size - 1;
++ else
++ return 0;
++}
++
++
++
+ /*========================================================================================================================
+ * Low-level Packet transmission
+ */
+@@ -463,23 +491,23 @@
+ packet->headerlen = 0;
+
+ /* create generic packet header */
+- hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
++ hlen = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
+
+ if ( session->http ) {
+ /* http connection only */
+- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
++ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "s=" );
+ if ( session->http_sesid > 0 ) {
+- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
++ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
+ }
+ session->http_seqno++;
+- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
++ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
+ }
+
+- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
++ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
+
+ if ( !session->http ) {
+ /* socket connection only */
+- packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
++ packet->headerlen = scnprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
+ }
+
+ /* copy the header to packet */
+@@ -716,7 +744,7 @@
+ clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
+ "%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */
+ "%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */
+@@ -760,7 +788,7 @@
+ clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
+ "%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */
+ "%s%c%s%c" /* dialingcode\1locale\1 */
+@@ -774,7 +802,7 @@
+ /* include "custom resource" information */
+ splashId = splash_current( session );
+ if ( splashId != NULL )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
+@@ -804,7 +832,7 @@
+ markuped_msg = g_strdup( msg );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
+ to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
+ );
+@@ -831,14 +859,14 @@
+ int datalen;
+ unsigned int i;
+
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
+ ( username ? username : "" ), CP_FLD_TERM, nr_attrib
+ );
+
+ /* add attributes */
+ for ( i = 0; i < nr_attrib; i++ )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
+@@ -864,7 +892,7 @@
+ parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
+ ( password ) ? password : "", CP_FLD_TERM, nr_attrib
+ );
+@@ -876,7 +904,7 @@
+ g_strfreev( parts );
+ return;
+ }
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen,
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen,
+ "%c%s%c%s%c%s", /* \1name\1type\1value */
+ CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
+ }
+@@ -904,13 +932,13 @@
+ unsigned int i;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+ CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+
+ /* add attributes */
+ for ( i = 0; i < nr_attrib; i++ )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+@@ -933,13 +961,13 @@
+ unsigned int i;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+ CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+
+ /* add attributes */
+ for ( i = 0; i < nr_attrib; i++ )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+@@ -959,14 +987,14 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%i%c", /* "ms"=show\1status */
+ presence, CP_FLD_TERM
+ );
+
+ /* append status message (if one is set) */
+ if ( statusmsg )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
+@@ -985,7 +1013,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%i", /* "ms"=mood */
+ mood
+ );
+@@ -1011,7 +1039,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
+ groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
+ CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
+@@ -1036,7 +1064,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=username */
+ username
+ );
+@@ -1059,7 +1087,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
+ username, CP_FLD_TERM, "", CP_FLD_TERM, alias
+ );
+@@ -1082,14 +1110,14 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=username */
+ username
+ );
+
+ /* append reason (if one is set) */
+ if ( reason )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
+@@ -1110,7 +1138,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
+ groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
+ );
+@@ -1132,7 +1160,7 @@
+ int datalen;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s", /* "ms"=splashId */
+ splashid
+ );
+@@ -1158,7 +1186,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
+ to, CP_FLD_TERM, id, CP_FLD_TERM, event
+ );
+@@ -1183,14 +1211,14 @@
+ int i;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
+ groupname, CP_FLD_TERM, nr_usernames
+ );
+
+ /* add usernames */
+ for ( i = 0; i < nr_usernames; i++ )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
+@@ -1212,14 +1240,14 @@
+ int i;
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ),
++ datalen = scnprintf( data, sizeof( data ),
+ "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
+ roomid, CP_FLD_TERM, nr_usernames
+ );
+
+ /* add usernames */
+ for ( i = 0; i < nr_usernames; i++ )
+- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
++ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+
+ /* queue packet for transmission */
+ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
+@@ -1245,7 +1273,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+@@ -1281,7 +1309,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+@@ -1319,7 +1347,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+@@ -1355,7 +1383,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+@@ -1392,7 +1420,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+@@ -1431,7 +1459,7 @@
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
+
+ /* convert the packet to a byte stream */
+- datalen = g_snprintf( data, sizeof( data ), "ms=" );
++ datalen = scnprintf( data, sizeof( data ), "ms=" );
+
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2369.patch pidgin-2.10.10/debian/patches/CVE-2016-2369.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2369.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2369.patch 2016-06-24 18:42:15.000000000 +1000
@@ -0,0 +1,20 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464902518 18000
+# Branch release-2.x.y
+# Node ID 7b52ca213832882c9f69b836560ba44c6e929a34
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0137
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -2710,7 +2710,8 @@
+ /* new record */
+ if ( packet.rcount == 1 ) {
+ /* packet command */
+- packet.cmd = atoi( packet.records[0]->fields[0]->data );
++ if ( packet.records[0]->fcount > 0 )
++ packet.cmd = atoi( packet.records[0]->fields[0]->data );
+ }
+ else if ( packet.rcount == 2 ) {
+ /* special case: binary multimedia packets should not be parsed here */
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2370.patch pidgin-2.10.10/debian/patches/CVE-2016-2370.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2370.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2370.patch 2016-06-27 18:33:10.000000000 +1000
@@ -0,0 +1,408 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464978366 18000
+# Branch release-2.x.y
+# Node ID fe0e01b2840740d9a07acf9a9788ec22e9dd120f
+# Parent bb5701f8ae79d6f6a1be7a99b256a8360436be98
+Fix for TALOS-CAN-0138
+
+diff --git a/libpurple/protocols/mxit/chunk.c b/libpurple/protocols/mxit/chunk.c
+--- a/libpurple/protocols/mxit/chunk.c
++++ b/libpurple/protocols/mxit/chunk.c
+@@ -151,11 +151,15 @@
+ * Extract a single byte from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param value The byte
+ * @return The number of bytes extracted.
+ */
+-static int get_int8( const char* chunkdata, char* value )
++static int get_int8( const char* chunkdata, size_t chunklen, char* value )
+ {
++ if ( chunklen < sizeof( char ) )
++ return 0;
++
+ *value = *chunkdata;
+
+ return sizeof( char );
+@@ -165,11 +169,15 @@
+ * Extract a 16-bit value from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param value The 16-bit value
+ * @return The number of bytes extracted
+ */
+-static int get_int16( const char* chunkdata, unsigned short* value )
++static int get_int16( const char* chunkdata, size_t chunklen, unsigned short* value )
+ {
++ if ( chunklen < sizeof( short ) )
++ return 0;
++
+ *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
+
+ return sizeof( short );
+@@ -179,11 +187,15 @@
+ * Extract a 32-bit value from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param value The 32-bit value
+ * @return The number of bytes extracted
+ */
+-static int get_int32( const char* chunkdata, unsigned int* value )
++static int get_int32( const char* chunkdata, size_t chunklen, unsigned int* value )
+ {
++ if ( chunklen < sizeof( int ) )
++ return 0;
++
+ *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
+
+ return sizeof( int );
+@@ -194,11 +206,15 @@
+ * Extract a 64-bit value from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param value The 64-bit value
+ * @return The number of bytes extracted
+ */
+-static int get_int64( const char* chunkdata, int64_t* value )
++static int get_int64( const char* chunkdata, size_t chunklen, int64_t* value )
+ {
++ if ( chunklen < sizeof( int64_t ) )
++ return 0;
++
+ *value = SWAP_64( *( (const int64_t*) chunkdata ) ); /* host byte-order */
+
+ return sizeof( int64_t );
+@@ -209,12 +225,16 @@
+ * Copy a block of data from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param dest Where to store the extract data
+ * @param datalen The length of the data to extract
+ * @return The number of bytes extracted
+ */
+-static int get_data( const char* chunkdata, char* dest, int datalen )
++static int get_data( const char* chunkdata, size_t chunklen, char* dest, size_t datalen )
+ {
++ if ( chunklen < datalen )
++ return 0;
++
+ memcpy( dest, chunkdata, datalen );
+
+ return datalen;
+@@ -224,20 +244,25 @@
+ * Extract a UTF-8 encoded string from the chunked data.
+ *
+ * @param chunkdata The chunked-data buffer
++ * @param chunklen The amount of data available in the buffer.
+ * @param str A pointer to extracted string. Must be g_free()'d.
+ * @param maxstrlen Maximum size of destination buffer.
+ * @return The number of bytes consumed
+ */
+-static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
++static int get_utf8_string( const char* chunkdata, size_t chunklen, char* str, size_t maxstrlen )
+ {
+- int pos = 0;
+- unsigned short len;
+- int skip = 0;
++ size_t pos = 0;
++ unsigned short len = 0;
++ size_t skip = 0;
+
+ /* string length [2 bytes] */
+- pos += get_int16( &chunkdata[pos], &len );
++ pos += get_int16( &chunkdata[pos], chunklen - pos, &len );
+
+- if ( len > maxstrlen ) {
++ if ( ( len + pos ) > chunklen ) {
++ /* string length is longer than chunk size */
++ return 0;
++ }
++ else if ( len > maxstrlen ) {
+ /* possible buffer overflow */
+ purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
+ skip = len - maxstrlen;
+@@ -245,7 +270,7 @@
+ }
+
+ /* string data */
+- pos += get_data( &chunkdata[pos], str, len );
++ pos += get_data( &chunkdata[pos], chunklen - pos, str, len );
+ str[len] = '\0'; /* terminate string */
+
+ return pos + skip;
+@@ -453,27 +478,27 @@
+ */
+ gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen );
+
+ memset( offer, 0, sizeof( struct offerfile_chunk ) );
+
+ /* id [8 bytes] */
+- pos += get_data( &chunkdata[pos], offer->fileid, 8);
++ pos += get_data( &chunkdata[pos], datalen - pos, offer->fileid, 8);
+
+ /* from username [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->username, sizeof( offer->username ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->username, sizeof( offer->username ) );
+ mxit_strip_domain( offer->username );
+
+ /* file size [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(offer->filesize) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(offer->filesize) );
+
+ /* filename [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->filename, sizeof( offer->filename ) );
+
+ /* mime type [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->mimetype, sizeof( offer->mimetype ) );
+
+ /* timestamp [8 bytes] */
+ /* not used by libPurple */
+@@ -501,7 +526,7 @@
+ */
+ gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen );
+
+@@ -512,19 +537,24 @@
+ return FALSE;
+
+ /* id [8 bytes] */
+- pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
++ pos += get_data( &chunkdata[pos], datalen - pos, getfile->fileid, 8 );
+
+ /* offset [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->offset) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->offset) );
+
+ /* file length [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->length) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->length) );
+
+ /* crc [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->crc) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->crc) );
++
++ /* check length does not exceed chunked data length */
++ if ( getfile->length > datalen - pos )
++ return FALSE;
+
+ /* file data */
+- getfile->data = &chunkdata[pos];
++ if ( getfile->length > 0 )
++ getfile->data = &chunkdata[pos];
+
+ return TRUE;
+ }
+@@ -540,23 +570,28 @@
+ */
+ gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen );
+
+ memset( splash, 0, sizeof( struct splash_chunk ) );
+
++ /* ensure that the chunk size is atleast the minimum size for a "splash screen" chunk */
++ if ( datalen < 6 )
++ return FALSE;
++
+ /* anchor [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(splash->anchor) );
++ pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->anchor) );
+
+ /* time to show [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(splash->showtime) );
++ pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->showtime) );
+
+ /* background color [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(splash->bgcolor) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(splash->bgcolor) );
+
+ /* file data */
+- splash->data = &chunkdata[pos];
++ if ( pos < datalen )
++ splash->data = &chunkdata[pos];
+
+ /* data length */
+ splash->datalen = datalen - pos;
+@@ -575,38 +610,44 @@
+ */
+ gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
+ {
+- int pos = 0;
+- unsigned int chunklen = 0;
++ size_t pos = 0;
++ unsigned int chunkslen = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen );
+
+ memset( cr, 0, sizeof( struct cr_chunk ) );
+
+ /* id [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->id, sizeof( cr->id ) );
+
+ /* handle [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->handle, sizeof( cr->handle ) );
+
+ /* operation [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(cr->operation) );
++ pos += get_int8( &chunkdata[pos], datalen - pos, &(cr->operation) );
+
+- /* chunk size [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &chunklen );
++ /* total length of all the chunks that are included [4 bytes] */
++ pos += get_int32( &chunkdata[pos], datalen - pos, &chunkslen );
++
++ /* ensure the chunks size does not exceed the data size */
++ if ( pos + chunkslen > datalen )
++ return FALSE;
+
+ /* parse the resource chunks */
+- while ( chunklen > 0 ) {
+- gchar* chunk = &chunkdata[pos];
++ while ( chunkslen >= MXIT_CHUNK_HEADER_SIZE ) {
++ gchar* chunk = &chunkdata[pos];
++ guint32 chunksize = chunk_length( chunk );
+
+- /* start of chunk data */
+- pos += MXIT_CHUNK_HEADER_SIZE;
++ /* check chunk size against length of received data */
++ if ( pos + MXIT_CHUNK_HEADER_SIZE + chunksize > datalen )
++ return FALSE;
+
+ switch ( chunk_type( chunk ) ) {
+ case CP_CHUNK_SPLASH : /* splash image */
+ {
+ struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
+
+- if ( mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash ) )
++ if ( mxit_chunk_parse_splash( chunk_data( chunk ), chunksize, splash ) )
+ cr->resources = g_list_append( cr->resources, splash );
+ else
+ g_free( splash );
+@@ -624,8 +665,8 @@
+ }
+
+ /* skip over data to next resource chunk */
+- pos += chunk_length( chunk );
+- chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) );
++ pos += MXIT_CHUNK_HEADER_SIZE + chunksize;
++ chunkslen -= ( MXIT_CHUNK_HEADER_SIZE + chunksize );
+ }
+
+ return TRUE;
+@@ -642,7 +683,7 @@
+ */
+ gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
+ {
+- int pos = 0;
++ size_t pos = 0;
+ unsigned short entries = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen );
+@@ -650,19 +691,19 @@
+ memset( sendfile, 0, sizeof( struct sendfile_chunk ) );
+
+ /* number of entries [2 bytes] */
+- pos += get_int16( &chunkdata[pos], &entries );
++ pos += get_int16( &chunkdata[pos], datalen - pos, &entries );
+
+ if ( entries < 1 ) /* no data */
+ return FALSE;
+
+ /* contactAddress [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->username, sizeof( sendfile->username ) );
+
+ /* status [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(sendfile->status) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(sendfile->status) );
+
+ /* status message [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
+
+ return TRUE;
+ }
+@@ -678,7 +719,7 @@
+ */
+ gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
+ {
+- int pos = 0;
++ size_t pos = 0;
+ unsigned int numfiles = 0;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen );
+@@ -686,37 +727,42 @@
+ memset( avatar, 0, sizeof( struct getavatar_chunk ) );
+
+ /* number of files [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &numfiles );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &numfiles );
+
+ if ( numfiles < 1 ) /* no data */
+ return FALSE;
+
+ /* mxitId [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->mxitid, sizeof( avatar->mxitid ) );
+
+ /* avatar id [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->avatarid, sizeof( avatar->avatarid ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->avatarid, sizeof( avatar->avatarid ) );
+
+ /* format [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->format, sizeof( avatar->format ) );
++ pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->format, sizeof( avatar->format ) );
+
+ /* bit depth [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) );
++ pos += get_int8( &chunkdata[pos], datalen - pos, &(avatar->bitdepth) );
+
+ /* crc [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->crc) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->crc) );
+
+ /* width [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->width) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->width) );
+
+ /* height [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->height) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->height) );
+
+ /* file length [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->length) );
++ pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->length) );
++
++ /* check length does not exceed chunked data length */
++ if ( avatar->length > datalen - pos )
++ return FALSE;
+
+ /* file data */
+- avatar->data = &chunkdata[pos];
++ if ( avatar->length > 0 )
++ avatar->data = &chunkdata[pos];
+
+ return TRUE;
+ }
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2371.patch pidgin-2.10.10/debian/patches/CVE-2016-2371.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2371.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2371.patch 2016-06-27 18:02:57.000000000 +1000
@@ -0,0 +1,23 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464972610 18000
+# Branch release-2.x.y
+# Node ID f0287378203fbf496a9890bf273d96adefb93b74
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0139
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -1863,6 +1863,12 @@
+ /* set the count for attributes */
+ count = atoi( records[0]->fields[1]->data );
+
++ /* ensure the packet has the correct number of fields */
++ if ( records[0]->fcount < ( 2 + ( count * 3 ) ) ) {
++ purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in extprofile response. fields=%i records=%i", records[0]->fcount, count );
++ return;
++ }
++
+ for ( i = 0; i < count; i++ ) {
+ char* fname;
+ char* fvalue;
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2373.patch pidgin-2.10.10/debian/patches/CVE-2016-2373.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2373.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2373.patch 2016-06-24 18:42:16.000000000 +1000
@@ -0,0 +1,66 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464889790 18000
+# Branch release-2.x.y
+# Node ID e6159ad42c4c557adb8aaae8e08aff084ef8bb8e
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0141
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -1735,6 +1735,24 @@
+
+
+ /*------------------------------------------------------------------------
++ * Parse the received mood value, and ensure that it is supported.
++ *
++ * @param value The received mood value.
++ * @return A valid mood value.
++ */
++static short mxit_parse_mood( const char* value )
++{
++ short mood = atoi( value );
++
++ /* ensure that the mood value is valid */
++ if ( ( mood >= MXIT_MOOD_NONE ) && ( mood <= MXIT_MOOD_STRESSED ) )
++ return mood;
++
++ return MXIT_MOOD_NONE;
++}
++
++
++/*------------------------------------------------------------------------
+ * Process a received contact update packet.
+ *
+ * @param session The MXit session object
+@@ -1767,7 +1785,7 @@
+
+ contact->presence = mxit_parse_presence( rec->fields[3]->data );
+ contact->type = atoi( rec->fields[4]->data );
+- contact->mood = atoi( rec->fields[5]->data );
++ contact->mood = mxit_parse_mood( rec->fields[5]->data );
+
+ if ( rec->fcount > 6 ) {
+ /* added in protocol 5.9 - flags & subtype */
+@@ -1824,7 +1842,7 @@
+ if ( rec->fcount >= 7 ) /* flags field is included */
+ flags = atoi( rec->fields[6]->data );
+
+- mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
++ mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), mxit_parse_mood( rec->fields[2]->data ),
+ rec->fields[3]->data, rec->fields[4]->data, flags );
+ mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
+ }
+--- a/libpurple/protocols/mxit/roster.c
++++ b/libpurple/protocols/mxit/roster.c
+@@ -473,10 +473,6 @@
+ contact->mood = mood;
+ contact->capabilities = flags;
+
+- /* validate mood */
+- if ( ( contact->mood < MXIT_MOOD_NONE ) || ( contact->mood > MXIT_MOOD_STRESSED ) )
+- contact->mood = MXIT_MOOD_NONE;
+-
+ g_strlcpy( contact->customMood, customMood, sizeof( contact->customMood ) );
+ // TODO: Download custom mood frame.
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2374.patch pidgin-2.10.10/debian/patches/CVE-2016-2374.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2374.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2374.patch 2016-06-24 18:42:17.000000000 +1000
@@ -0,0 +1,19 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464901903 18000
+# Branch release-2.x.y
+# Node ID f6c08d962618f0d097b840e116c1221625677bb0
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0142
+
+--- a/libpurple/protocols/mxit/multimx.c
++++ b/libpurple/protocols/mxit/multimx.c
+@@ -360,7 +360,7 @@
+ unsigned int i;
+
+ for (i = 1; i < strlen(msg); i++) { /* search for end of nickname */
+- if (msg[i] == '>') {
++ if ((msg[i] == '>') && (msg[i+1] == '\n')) {
+ msg[i] = '\0';
+ g_free(mx->from);
+ mx->from = g_strdup(&msg[1]);
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2375.patch pidgin-2.10.10/debian/patches/CVE-2016-2375.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2375.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2375.patch 2016-06-24 18:42:17.000000000 +1000
@@ -0,0 +1,48 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464973294 18000
+# Branch release-2.x.y
+# Node ID b786e9814536aa96a3f7c8674d588b04d11c57a7
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0143
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -2055,6 +2055,12 @@
+ * userid \1 contactType \1 value0 \1 value1 ... valueN
+ */
+
++ /* ensure that record[0] contacts the minumum number of fields */
++ if ( records[0]->fcount < 4 ) {
++ purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i", records[0]->fcount );
++ return;
++ }
++
+ /* the type of results */
+ searchType = atoi( records[0]->fields[0]->data );
+
+@@ -2064,11 +2070,24 @@
+ /* set the count for attributes */
+ count = atoi( records[0]->fields[3]->data );
+
++ /* ensure that record[0] contains the specified number of attributes */
++ if ( records[0]->fcount < ( 4 + count ) ) {
++ purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", records[0]->fcount, count );
++ return;
++ }
++
+ for ( i = 1; i < rcount; i ++ ) {
+ struct record* rec = records[i];
+ struct MXitProfile* profile = g_new0( struct MXitProfile, 1 );
+ int j;
+
++ /* ensure that each result contains the specified number of attributes */
++ if ( rec->fcount != ( 2 + count ) ) {
++ purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", rec->fcount, count );
++ g_free( profile );
++ continue;
++ }
++
+ g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
+ // TODO: ContactType - User or Service
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2376.patch pidgin-2.10.10/debian/patches/CVE-2016-2376.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2376.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2376.patch 2016-06-24 18:42:18.000000000 +1000
@@ -0,0 +1,21 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464900062 18000
+# Branch release-2.x.y
+# Node ID 19f89eda85875507ee37c9430bb8798f0afa5c0b
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0118
+
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -2888,8 +2888,9 @@
+ /* the end of the length record found */
+ session->rx_lbuf[session->rx_i] = '\0';
+ session->rx_res = atoi( &session->rx_lbuf[3] );
+- if ( session->rx_res > CP_MAX_PACKET ) {
++ if ( ( session->rx_res <= 0 ) || ( session->rx_res > CP_MAX_PACKET ) ) {
+ purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
++ return;
+ }
+ session->rx_state = RX_STATE_DATA;
+ session->rx_i = 0;
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2377.patch pidgin-2.10.10/debian/patches/CVE-2016-2377.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2377.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2377.patch 2016-06-24 18:42:19.000000000 +1000
@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464976918 18000
+# Branch release-2.x.y
+# Node ID 0f94ef13ab373f4da4a723377d792a296145efdb
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0119
+
+--- a/libpurple/protocols/mxit/http.c
++++ b/libpurple/protocols/mxit/http.c
+@@ -97,9 +97,9 @@
+ {
+ struct MXitSession* session = (struct MXitSession*) user_data;
+ char buf[256];
+- int buflen;
++ unsigned int buflen;
+ char* body;
+- int bodylen;
++ unsigned int bodylen;
+ char* ch;
+ int len;
+ char* tmp;
+@@ -182,7 +182,7 @@
+ goto done;
+ }
+ tmp = g_strndup( ch, tmp - ch );
+- bodylen = atoi( tmp );
++ bodylen = strtoul( tmp, NULL, 10 );
+ g_free( tmp );
+ tmp = NULL;
+
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2378.patch pidgin-2.10.10/debian/patches/CVE-2016-2378.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2378.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2378.patch 2016-06-24 18:42:38.000000000 +1000
@@ -0,0 +1,605 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464973641 18000
+# Branch release-2.x.y
+# Node ID 06278419c703cf6dd42a8add415480046ce9a05e
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0120
+
+--- a/libpurple/protocols/mxit/chunk.c
++++ b/libpurple/protocols/mxit/chunk.c
+@@ -168,7 +168,7 @@
+ * @param value The 16-bit value
+ * @return The number of bytes extracted
+ */
+-static int get_int16( const char* chunkdata, short* value )
++static int get_int16( const char* chunkdata, unsigned short* value )
+ {
+ *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
+
+@@ -182,7 +182,7 @@
+ * @param value The 32-bit value
+ * @return The number of bytes extracted
+ */
+-static int get_int32( const char* chunkdata, int* value )
++static int get_int32( const char* chunkdata, unsigned int* value )
+ {
+ *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
+
+@@ -230,9 +230,9 @@
+ */
+ static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
+ {
+- int pos = 0;
+- short len;
+- int skip = 0;
++ int pos = 0;
++ unsigned short len;
++ int skip = 0;
+
+ /* string length [2 bytes] */
+ pos += get_int16( &chunkdata[pos], &len );
+@@ -263,9 +263,9 @@
+ * @param fileid A unique ID that identifies this file
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_reject( char* chunkdata, const char* fileid )
++size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ /* file id [8 bytes] */
+ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+@@ -289,9 +289,9 @@
+ * @param offset The start offset in the file
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset )
++size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ /* file id [8 bytes] */
+ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+@@ -314,9 +314,9 @@
+ * @param status The status of the file transfer (see chunk.h)
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
++size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ /* file id [8 bytes] */
+ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+@@ -338,9 +338,9 @@
+ * @param datalen The size of the file contents
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen )
++size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen )
+ {
+- int pos = 0;
++ size_t pos = 0;
+ const char* mime = NULL;
+
+ /* data length [4 bytes] */
+@@ -380,10 +380,10 @@
+ * @param datalen The size of the avatar data
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen )
++size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen )
+ {
+ char fileid[MXIT_CHUNK_FILEID_LEN];
+- int pos = 0;
++ size_t pos = 0;
+
+ /* id [8 bytes] */
+ memset( &fileid, 0, sizeof( fileid ) ); /* set to 0 for file upload */
+@@ -410,9 +410,9 @@
+ * @param avatarId The Id of the avatar image (as string)
+ * @return The number of bytes encoded in the buffer
+ */
+-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
++size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
+ {
+- int pos = 0;
++ size_t pos = 0;
+
+ /* number of avatars [4 bytes] */
+ pos += add_int32( &chunkdata[pos], 1 );
+@@ -450,11 +450,11 @@
+ * @param datalen The length of the chunked data
+ * @param offer Decoded offerfile information
+ */
+-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer )
++void mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer )
+ {
+- int pos = 0;
++ int pos = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen );
+
+ /* id [8 bytes] */
+ pos += get_data( &chunkdata[pos], offer->fileid, 8);
+@@ -493,11 +493,11 @@
+ * @param datalen The length of the chunked data
+ * @param offer Decoded getfile information
+ */
+-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile )
++void mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile )
+ {
+ int pos = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen );
+
+ /* id [8 bytes] */
+ pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+@@ -523,11 +523,11 @@
+ * @param datalen The length of the chunked data
+ * @param splash Decoded splash image information
+ */
+-static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash_chunk* splash )
++static void mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash )
+ {
+ int pos = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen );
+
+ /* anchor [1 byte] */
+ pos += get_int8( &chunkdata[pos], &(splash->anchor) );
+@@ -553,12 +553,12 @@
+ * @param datalen The length of the chunked data
+ * @param offer Decoded custom resource
+ */
+-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
++void mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr )
+ {
+- int pos = 0;
+- int chunklen = 0;
++ int pos = 0;
++ unsigned int chunklen = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen );
+
+ /* id [UTF-8] */
+ pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
+@@ -614,12 +614,12 @@
+ * @param datalen The length of the chunked data
+ * @param sendfile Decoded sendfile information
+ */
+-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile )
++void mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile )
+ {
+- int pos = 0;
+- short entries = 0;
++ int pos = 0;
++ unsigned short entries = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen );
+
+ /* number of entries [2 bytes] */
+ pos += get_int16( &chunkdata[pos], &entries );
+@@ -645,12 +645,12 @@
+ * @param datalen The length of the chunked data
+ * @param avatar Decoded avatar information
+ */
+-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar )
++void mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar )
+ {
+- int pos = 0;
+- int numfiles = 0;
++ int pos = 0;
++ unsigned int numfiles = 0;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%i bytes)\n", datalen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen );
+
+ /* number of files [4 bytes] */
+ pos += get_int32( &chunkdata[pos], &numfiles );
+--- a/libpurple/protocols/mxit/chunk.h
++++ b/libpurple/protocols/mxit/chunk.h
+@@ -103,22 +103,22 @@
+ * Offer File chunk (6).
+ */
+ struct offerfile_chunk {
+- char fileid[MXIT_CHUNK_FILEID_LEN];
+- char username[MXIT_CP_MAX_JID_LEN + 1];
+- int filesize;
+- char filename[FILENAME_MAX];
+- char mimetype[64];
++ char fileid[MXIT_CHUNK_FILEID_LEN];
++ char username[MXIT_CP_MAX_JID_LEN + 1];
++ unsigned int filesize;
++ char filename[FILENAME_MAX];
++ char mimetype[64];
+ };
+
+ /*
+ * Get File chunk (8) response.
+ */
+ struct getfile_chunk {
+- char fileid[MXIT_CHUNK_FILEID_LEN];
+- int offset;
+- int length;
+- int crc;
+- char* data;
++ char fileid[MXIT_CHUNK_FILEID_LEN];
++ unsigned int offset;
++ unsigned int length;
++ unsigned int crc;
++ char* data;
+ };
+
+ /*
+@@ -135,11 +135,11 @@
+ * Splash Image chunk (2)
+ */
+ struct splash_chunk {
+- char anchor;
+- char showtime;
+- int bgcolor;
+- char* data;
+- int datalen;
++ char anchor;
++ char showtime;
++ unsigned int bgcolor;
++ char* data;
++ unsigned int datalen;
+ };
+
+ /*
+@@ -153,40 +153,40 @@
+ * Get Avatar chunk (14) response.
+ */
+ struct getavatar_chunk {
+- char mxitid[50];
+- char avatarid[64];
+- char format[16];
+- char bitdepth;
+- int crc;
+- int width;
+- int height;
+- int length;
+- char* data;
++ char mxitid[50];
++ char avatarid[64];
++ char format[16];
++ char bitdepth;
++ unsigned int crc;
++ unsigned int width;
++ unsigned int height;
++ unsigned int length;
++ char* data;
+ };
+
+ /*
+ * Send File Direct chunk (10) response.
+ */
+ struct sendfile_chunk {
+- char username[MXIT_CP_MAX_JID_LEN + 1];
+- int status;
+- char statusmsg[1024];
++ char username[MXIT_CP_MAX_JID_LEN + 1];
++ unsigned int status;
++ char statusmsg[1024];
+ };
+
+ /* Encode chunk */
+-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen );
+-int mxit_chunk_create_reject( char* chunkdata, const char* fileid );
+-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset );
+-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
+-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen );
+-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
++size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen );
++size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid );
++size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset );
++size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
++size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen );
++size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
+
+ /* Decode chunk */
+-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer );
+-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile );
+-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr );
+-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile );
+-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar );
++void mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer );
++void mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile );
++void mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr );
++void mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile );
++void mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar );
+
+ #endif /* _MXIT_CHUNK_H_ */
+
+--- a/libpurple/protocols/mxit/filexfer.c
++++ b/libpurple/protocols/mxit/filexfer.c
+@@ -357,7 +357,7 @@
+ * @param filesize The size of the file being offered
+ * @param fileid A unique ID that identifies this file
+ */
+-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid )
++void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid )
+ {
+ PurpleXfer* xfer = NULL;
+ struct mxitxfer* mx = NULL;
+@@ -373,7 +373,7 @@
+ xfer->data = mx;
+
+ purple_xfer_set_filename( xfer, filename );
+- if( filesize > 0 )
++ if ( filesize > 0 )
+ purple_xfer_set_size( xfer, filesize );
+
+ /* register file transfer callback functions */
+@@ -429,7 +429,7 @@
+ * @param data The file data
+ * @param datalen The size of the data
+ */
+-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
++void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen )
+ {
+ PurpleXfer* xfer = NULL;
+
+--- a/libpurple/protocols/mxit/filexfer.h
++++ b/libpurple/protocols/mxit/filexfer.h
+@@ -43,8 +43,8 @@
+ PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who );
+
+ /* MXit Protocol callbacks */
+-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid );
+-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen );
++void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid );
++void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen );
+
+
+ #endif /* _MXIT_FILEXFER_H_ */
+--- a/libpurple/protocols/mxit/protocol.c
++++ b/libpurple/protocols/mxit/protocol.c
+@@ -1263,14 +1263,14 @@
+ * @param buf The content of the file
+ * @param buflen The length of the file contents
+ */
+-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
++void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen )
+ {
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
++ purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username );
+
+ /* convert the packet to a byte stream */
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
+@@ -1278,15 +1278,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
+ set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+@@ -1304,7 +1300,7 @@
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
+
+@@ -1314,15 +1310,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
+ set_chunk_type( chunk, CP_CHUNK_REJECT );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+@@ -1337,12 +1329,12 @@
+ * @param filesize The number of bytes to retrieve
+ * @param offset Offset in file at which to start retrieving
+ */
+-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
++void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset )
+ {
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
+
+@@ -1352,15 +1344,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
+ set_chunk_type( chunk, CP_CHUNK_GET );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+@@ -1378,7 +1366,7 @@
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
+
+@@ -1388,15 +1376,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
+ set_chunk_type( chunk, CP_CHUNK_RECEIVED );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+@@ -1410,14 +1394,14 @@
+ * @param data The avatar data
+ * @param buflen The length of the avatar data
+ */
+-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
++void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen )
+ {
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
++ purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen );
+
+ /* convert the packet to a byte stream */
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
+@@ -1425,15 +1409,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
+ set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+@@ -1454,7 +1434,7 @@
+ char data[CP_MAX_PACKET];
+ int datalen = 0;
+ gchar* chunk;
+- int size;
++ size_t chunksize;
+
+ purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
+
+@@ -1464,15 +1444,11 @@
+ /* map chunk header over data buffer */
+ chunk = &data[datalen];
+
+- size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
+- return;
+- }
+-
++ /* encode chunk */
++ chunksize = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
+ set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
++ set_chunk_length( chunk, chunksize );
++ datalen += MXIT_CHUNK_HEADER_SIZE + chunksize;
+
+ /* send the byte stream to the mxit server */
+ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+--- a/libpurple/protocols/mxit/protocol.h
++++ b/libpurple/protocols/mxit/protocol.h
+@@ -332,11 +332,11 @@
+ void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
+ void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
+
+-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
++void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen );
+ void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
+-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
++void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset );
+ void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
+-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
++void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen );
+ void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
+
+ void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
+--- a/libpurple/protocols/mxit/splashscreen.c
++++ b/libpurple/protocols/mxit/splashscreen.c
+@@ -112,7 +112,7 @@
+ * @param data Splash-screen image data (PNG format)
+ * @param datalen Splash-screen image data size
+ */
+-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable)
++void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable)
+ {
+ char* dir;
+ char* filename;
+--- a/libpurple/protocols/mxit/splashscreen.h
++++ b/libpurple/protocols/mxit/splashscreen.h
+@@ -44,7 +44,7 @@
+ /*
+ * Save a new splash-screen.
+ */
+-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable);
++void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable);
+
+ /*
+ * Remove the stored splash-screen (if it exists).
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-2380.patch pidgin-2.10.10/debian/patches/CVE-2016-2380.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-2380.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-2380.patch 2016-06-24 18:42:39.000000000 +1000
@@ -0,0 +1,43 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464901499 18000
+# Branch release-2.x.y
+# Node ID 8172584fd6409f72f7799afad5c0cf55c43a5b08
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix for TALOS-CAN-0123
+
+--- a/libpurple/protocols/mxit/markup.c
++++ b/libpurple/protocols/mxit/markup.c
+@@ -1083,7 +1083,6 @@
+ GList* entry;
+ GList* tagstack = NULL;
+ char* reply;
+- char color[8];
+ int len = strlen ( message );
+ int i;
+
+@@ -1145,12 +1144,18 @@
+ }
+ else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) {
+ /* font colour */
+- tag = g_new0( struct tag, 1 );
+- tag->type = MXIT_TAG_COLOR;
+- tagstack = g_list_append( tagstack, tag );
+- memset( color, 0x00, sizeof( color ) );
+- memcpy( color, &message[i + 13], 7 );
+- g_string_append( mx, color );
++ char color[8];
++
++ /* ensure we have the complete tag: <font color="#123456"> */
++ if ( i + 20 < len ) {
++ tag = g_new0( struct tag, 1 );
++ tag->type = MXIT_TAG_COLOR;
++ tagstack = g_list_append( tagstack, tag );
++
++ memset( color, 0x00, sizeof( color ) );
++ memcpy( color, &message[i + 13], 7 );
++ g_string_append( mx, color );
++ }
+ }
+ else if ( purple_str_has_prefix( &message[i], "</font>" ) ) {
+ /* end of font tag */
diff -Nru pidgin-2.10.10/debian/patches/CVE-2016-4323.patch pidgin-2.10.10/debian/patches/CVE-2016-4323.patch
--- pidgin-2.10.10/debian/patches/CVE-2016-4323.patch 1970-01-01 10:00:00.000000000 +1000
+++ pidgin-2.10.10/debian/patches/CVE-2016-4323.patch 2016-06-24 18:42:13.000000000 +1000
@@ -0,0 +1,28 @@
+# HG changeset patch
+# User Andrew Victor <andrew.victor@mxit.com>
+# Date 1464897853 18000
+# Branch release-2.x.y
+# Node ID 5fa3f2bc69d7918d1e537e780839df63d5df59aa
+# Parent 5e5e84e8a79890e580158ac2eae073d7394e93b7
+Fix TALOS-CAN-0128
+
+--- a/libpurple/protocols/mxit/splashscreen.c
++++ b/libpurple/protocols/mxit/splashscreen.c
+@@ -93,7 +93,7 @@
+ purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId);
+
+ /* Delete stored splash image */
+- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId);
++ filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
+ g_unlink(filename);
+ g_free(filename);
+
+@@ -179,7 +179,7 @@
+ purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId);
+
+ /* Load splash-screen image from file */
+- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId);
++ filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId));
+ if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) {
+ char buf[128];
+
diff -Nru pidgin-2.10.10/debian/patches/series pidgin-2.10.10/debian/patches/series
--- pidgin-2.10.10/debian/patches/series 2014-01-26 03:57:00.000000000 +1100
+++ pidgin-2.10.10/debian/patches/series 2016-06-27 18:58:12.000000000 +1000
@@ -0,0 +1,18 @@
+CVE-2016-2365.patch
+CVE-2016-2366.patch
+CVE-2016-2368-1.patch
+CVE-2016-2368-2.patch
+CVE-2016-2369.patch
+CVE-2016-2371.patch
+CVE-2016-2373.patch
+CVE-2016-2374.patch
+CVE-2016-2375.patch
+CVE-2016-2376.patch
+CVE-2016-2377.patch
+CVE-2016-2378.patch
+CVE-2016-2380.patch
+CVE-2016-2367-1.patch
+CVE-2016-2367-2.patch
+CVE-2016-2367-3.patch
+CVE-2016-2370.patch
+CVE-2016-4323.patch
Reply to:
- Follow-Ups:
- Re: pidgin
- From: Brian May <bam@debian.org>
- Re: pidgin
- From: Salvatore Bonaccorso <carnil@debian.org>