comparison pidgin/gtkimhtml.c @ 29468:89b4054deba1

Fix CVE-2010-0423, a denial of service attack due to the parsing of large numbers of smileys. (Discovered by Antti Hayrynen)
author Mark Doliner <mark@kingant.net>
date Tue, 16 Feb 2010 09:02:23 +0000
parents f0e80126a3ce
children f549ad844d54
comparison
equal deleted inserted replaced
29467:40623dd0bba0 29468:89b4054deba1
2220 } 2220 }
2221 2221
2222 return smiley->icon; 2222 return smiley->icon;
2223 } 2223 }
2224 2224
2225 static GdkPixbufAnimation *
2226 gtk_smiley_tree_image (GtkIMHtml *imhtml,
2227 const gchar *sml,
2228 const gchar *text)
2229 {
2230 GtkIMHtmlSmiley *smiley;
2231
2232 smiley = gtk_imhtml_smiley_get(imhtml,sml,text);
2233
2234 if (!smiley)
2235 return NULL;
2236
2237 return gtk_smiley_get_image(smiley);
2238 }
2239
2240 #define VALID_TAG(x) do { \ 2225 #define VALID_TAG(x) do { \
2241 if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \ 2226 if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) { \
2242 if (tag) *tag = g_strndup (string, strlen (x)); \ 2227 if (tag) *tag = g_strndup (string, strlen (x)); \
2243 if (len) *len = strlen (x) + 1; \ 2228 if (len) *len = strlen (x) + 1; \
2244 return TRUE; \ 2229 return TRUE; \
2692 g_return_if_fail (text != NULL); 2677 g_return_if_fail (text != NULL);
2693 c = text; 2678 c = text;
2694 len = strlen(text); 2679 len = strlen(text);
2695 ws = g_malloc(len + 1); 2680 ws = g_malloc(len + 1);
2696 ws[0] = '\0'; 2681 ws[0] = '\0';
2682
2683 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(0));
2697 2684
2698 gtk_text_buffer_begin_user_action(imhtml->text_buffer); 2685 gtk_text_buffer_begin_user_action(imhtml->text_buffer);
2699 while (pos < len) { 2686 while (pos < len) {
2700 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { 2687 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) {
2701 c++; 2688 c++;
3545 } 3532 }
3546 sl = next; 3533 sl = next;
3547 } 3534 }
3548 gtk_text_buffer_delete(imhtml->text_buffer, start, end); 3535 gtk_text_buffer_delete(imhtml->text_buffer, start, end);
3549 3536
3537 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(0));
3538
3550 g_object_unref(object); 3539 g_object_unref(object);
3551 } 3540 }
3552 3541
3553 void gtk_imhtml_page_up (GtkIMHtml *imhtml) 3542 void gtk_imhtml_page_up (GtkIMHtml *imhtml)
3554 { 3543 {
4981 { 4970 {
4982 GdkPixbuf *pixbuf = NULL; 4971 GdkPixbuf *pixbuf = NULL;
4983 GdkPixbufAnimation *annipixbuf = NULL; 4972 GdkPixbufAnimation *annipixbuf = NULL;
4984 GtkWidget *icon = NULL; 4973 GtkWidget *icon = NULL;
4985 GtkTextChildAnchor *anchor = NULL; 4974 GtkTextChildAnchor *anchor = NULL;
4986 char *unescaped = purple_unescape_html(smiley); 4975 char *unescaped;
4987 GtkIMHtmlSmiley *imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped); 4976 GtkIMHtmlSmiley *imhtml_smiley;
4988 GtkWidget *ebox = NULL; 4977 GtkWidget *ebox = NULL;
4978 int numsmileys_thismsg, numsmileys_total;
4979
4980 /*
4981 * This GtkIMHtml has the maximum number of smileys allowed, so don't
4982 * add any more. We do this for performance reasons, because smileys
4983 * are apparently pretty inefficient. Hopefully we can remove this
4984 * restriction when we're using a better HTML widget.
4985 */
4986 numsmileys_thismsg = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg"));
4987 if (numsmileys_thismsg >= 30) {
4988 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1);
4989 return;
4990 }
4991 numsmileys_total = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total"));
4992 if (numsmileys_total >= 300) {
4993 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1);
4994 return;
4995 }
4996
4997 unescaped = purple_unescape_html(smiley);
4998 imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped);
4989 4999
4990 if (imhtml->format_functions & GTK_IMHTML_SMILEY) { 5000 if (imhtml->format_functions & GTK_IMHTML_SMILEY) {
4991 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); 5001 annipixbuf = imhtml_smiley ? gtk_smiley_get_image(imhtml_smiley) : NULL;
4992 if (annipixbuf) { 5002 if (annipixbuf) {
4993 if (gdk_pixbuf_animation_is_static_image(annipixbuf)) { 5003 if (gdk_pixbuf_animation_is_static_image(annipixbuf)) {
4994 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); 5004 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf);
4995 if (pixbuf) 5005 if (pixbuf)
4996 icon = gtk_image_new_from_pixbuf(pixbuf); 5006 icon = gtk_image_new_from_pixbuf(pixbuf);
5040 5050
5041 gtk_widget_show(icon); 5051 gtk_widget_show(icon);
5042 if (ebox) 5052 if (ebox)
5043 gtk_container_add(GTK_CONTAINER(ebox), icon); 5053 gtk_container_add(GTK_CONTAINER(ebox), icon);
5044 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor); 5054 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor);
5055
5056 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(numsmileys_thismsg + 1));
5057 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(numsmileys_total + 1));
5045 } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) { 5058 } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) {
5046 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); 5059 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
5047 imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, g_object_ref(anchor)); 5060 imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, g_object_ref(anchor));
5048 if (ebox) { 5061 if (ebox) {
5049 GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU); 5062 GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU);
5052 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); 5065 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free);
5053 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_tiptext", g_strdup(unescaped), g_free); 5066 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_tiptext", g_strdup(unescaped), g_free);
5054 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); 5067 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free);
5055 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor); 5068 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor);
5056 } 5069 }
5070
5071 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_thismsg", GINT_TO_POINTER(numsmileys_thismsg + 1));
5072 g_object_set_data(G_OBJECT(imhtml), "gtkimhtml_numsmileys_total", GINT_TO_POINTER(numsmileys_total + 1));
5057 } else { 5073 } else {
5058 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); 5074 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1);
5059 } 5075 }
5060 5076
5061 if (ebox) { 5077 if (ebox) {