Mercurial > pidgin.yaz
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) { |