# HG changeset patch # User Mark Doliner # Date 1266310943 0 # Node ID 89b4054deba1b044db6a91219452b3934ef61cc5 # Parent 40623dd0bba0a03b45f2155c20c1839c183dba3e Fix CVE-2010-0423, a denial of service attack due to the parsing of large numbers of smileys. (Discovered by Antti Hayrynen) diff -r 40623dd0bba0 -r 89b4054deba1 ChangeLog --- a/ChangeLog Tue Feb 16 08:58:45 2010 +0000 +++ b/ChangeLog Tue Feb 16 09:02:23 2010 +0000 @@ -27,7 +27,7 @@ MSN: * Fix CVE-2010-0277, a possible remote crash when parsing an incoming - SLP message. Discovered by Fabian Yamaguchi. + SLP message. (Discovered by Fabian Yamaguchi) * File transfer requests will no longer cause a crash if you delete the file before the other side accepts. * Received files will no longer hold an extra lock after completion, @@ -74,6 +74,8 @@ Mohta) Pidgin: + * Fix CVE-2010-0423, a denial of service attack due to the parsing + of large numbers of smileys. (Discovered by Antti Hayrynen) * Correctly size conversation and status box entries when the interior-focus style property is diabled. (Gabriel Schulhof) * Correctly handle a multiline text field being required in a diff -r 40623dd0bba0 -r 89b4054deba1 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Tue Feb 16 08:58:45 2010 +0000 +++ b/pidgin/gtkimhtml.c Tue Feb 16 09:02:23 2010 +0000 @@ -2222,21 +2222,6 @@ return smiley->icon; } -static GdkPixbufAnimation * -gtk_smiley_tree_image (GtkIMHtml *imhtml, - const gchar *sml, - const gchar *text) -{ - GtkIMHtmlSmiley *smiley; - - smiley = gtk_imhtml_smiley_get(imhtml,sml,text); - - if (!smiley) - return NULL; - - return gtk_smiley_get_image(smiley); -} - #define VALID_TAG(x) do { \ if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ if (tag) *tag = g_strndup (string, strlen (x)); \ @@ -2695,6 +2680,8 @@ ws = g_malloc(len + 1); ws[0] = '\0'; + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(0)); + gtk_text_buffer_begin_user_action(imhtml->text_buffer); while (pos < len) { if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { @@ -3547,6 +3534,8 @@ } gtk_text_buffer_delete(imhtml->text_buffer, start, end); + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(0)); + g_object_unref(object); } @@ -4983,12 +4972,33 @@ GdkPixbufAnimation *annipixbuf = NULL; GtkWidget *icon = NULL; GtkTextChildAnchor *anchor = NULL; - char *unescaped = purple_unescape_html(smiley); - GtkIMHtmlSmiley *imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped); + char *unescaped; + GtkIMHtmlSmiley *imhtml_smiley; GtkWidget *ebox = NULL; + int numsmileys_thismsg, numsmileys_total; + + /* + * This GtkIMHtml has the maximum number of smileys allowed, so don't + * add any more. We do this for performance reasons, because smileys + * are apparently pretty inefficient. Hopefully we can remove this + * restriction when we're using a better HTML widget. + */ + numsmileys_thismsg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg")); + if (numsmileys_thismsg >= 30) { + gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); + return; + } + numsmileys_total = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total")); + if (numsmileys_total >= 300) { + gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); + return; + } + + unescaped = purple_unescape_html(smiley); + imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped); if (imhtml->format_functions & GTK_IMHTML_SMILEY) { - annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); + annipixbuf = imhtml_smiley ? gtk_smiley_get_image(imhtml_smiley) : NULL; if (annipixbuf) { if (gdk_pixbuf_animation_is_static_image(annipixbuf)) { pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); @@ -5042,6 +5052,9 @@ if (ebox) gtk_container_add(GTK_CONTAINER(ebox), icon); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor); + + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(numsmileys_thismsg + 1)); + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(numsmileys_total + 1)); } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) { anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, g_object_ref(anchor)); @@ -5054,6 +5067,9 @@ g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor); } + + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(numsmileys_thismsg + 1)); + g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(numsmileys_total + 1)); } else { gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); }