Mercurial > pidgin.yaz
diff pidgin/gtkconv.c @ 32156:1693114a2655
applied changes from 6cf1aee8ac5e3c836af832eaf26ccedd611dc70b
through e802003adbf0be4496de3de8ac03b47c1e471d00
Original commit message:
Start looking at the GError parameter every time we call these functions:
- gdk_pixbuf_loader_write
- gdk_pixbuf_loader_close
- gdk_pixbuf_new_from_file
- gdk_pixbuf_new_from_file_at_size
- gdk_pixbuf_new_from_file_at_scale
There are times when gdkpixbuf returns a semi-invalid GdkPixbuf object and
also sets the GError. If this happens we want to discard and ignore the
GdkPixbuf object because it can cause problems. For example, calling
gdk_pixbuf_scale_simple() causes gdkpixbuf to rapidly consume memory in
an infinite loop. And that's bad.
This commit adds some helper functions to gtkutils.[c|h] that make it a
little easier to check the GError value. We should use them everywhere
we call any of the above functions.
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 22 Jun 2011 07:09:42 +0000 |
parents | 5ffd5582f5fe |
children | 47c604efed32 |
line wrap: on
line diff
--- a/pidgin/gtkconv.c Wed Jun 22 02:48:46 2011 +0000 +++ b/pidgin/gtkconv.c Wed Jun 22 07:09:42 2011 +0000 @@ -6408,8 +6408,8 @@ { PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; - GdkPixbufLoader *loader; const char *sml; + GError *error = NULL; sml = purple_account_get_protocol_name(conv->account); gtkconv = PIDGIN_CONVERSATION(conv); @@ -6422,11 +6422,24 @@ g_memmove((guchar *)smiley->data + smiley->datasize, data, size); smiley->datasize += size; - loader = smiley->loader; - if (!loader) + if (!smiley->loader) return; - gdk_pixbuf_loader_write(loader, data, size, NULL); + if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " + "failed with size=%zu: %s\n", size, + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + /* We must stop using the GdkPixbufLoader because trying to load + certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return + a GdkPixbuf that will cause some operations (like + gdk_pixbuf_scale_simple()) to consume memory in an infinite loop. + But we also don't want to set smiley->loader to NULL because our + code might expect it to be set. So create a new loader. */ + g_object_unref(G_OBJECT(smiley->loader)); + smiley->loader = gdk_pixbuf_loader_new(); + } } static void @@ -6434,8 +6447,8 @@ { PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; - GdkPixbufLoader *loader; const char *sml; + GError *error = NULL; g_return_if_fail(conv != NULL); g_return_if_fail(smile != NULL); @@ -6447,17 +6460,27 @@ if (!smiley) return; - loader = smiley->loader; - - if (!loader) + if (!smiley->loader) return; - - purple_debug_info("gtkconv", "About to close the smiley pixbuf\n"); - gdk_pixbuf_loader_close(loader, NULL); - + if (!gdk_pixbuf_loader_close(smiley->loader, &error) || error) { + purple_debug_warning("gtkconv", "gdk_pixbuf_loader_close() " + "failed: %s\n", + error ? error->message : "(no error message)"); + if (error) + g_error_free(error); + /* We must stop using the GdkPixbufLoader because if we tried to + load certain invalid GIFs with all current versions of GDK (as + of 2011-06-15) then it's possible the loader will contain data + that could cause some operations (like gdk_pixbuf_scale_simple()) + to consume memory in an infinite loop. But we also don't want + to set smiley->loader to NULL because our code might expect it + to be set. So create a new loader. */ + g_object_unref(G_OBJECT(smiley->loader)); + smiley->loader = gdk_pixbuf_loader_new(); + } } static void @@ -6957,10 +6980,6 @@ PurpleBuddy *buddy; - GdkPixbufLoader *loader; - GdkPixbufAnimation *anim; - GError *err = NULL; - PurpleStoredImage *custom_img = NULL; gconstpointer data = NULL; size_t len; @@ -7038,7 +7057,6 @@ if (data == NULL) { icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); - if (icon == NULL) { gtk_widget_set_size_request(gtkconv->u.im->icon_container, @@ -7047,7 +7065,6 @@ } data = purple_buddy_icon_get_data(icon, &len); - if (data == NULL) { gtk_widget_set_size_request(gtkconv->u.im->icon_container, @@ -7056,25 +7073,13 @@ } } - loader = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(loader, data, len, NULL); - gdk_pixbuf_loader_close(loader, &err); - + gtkconv->u.im->anim = pidgin_pixbuf_anim_from_data(data, len); purple_imgstore_unref(custom_img); - anim = gdk_pixbuf_loader_get_animation(loader); - if (anim) - g_object_ref(G_OBJECT(anim)); - g_object_unref(loader); - - if (!anim) + if (!gtkconv->u.im->anim) { + purple_debug_error("gtkconv", "Couldn't load icon for conv %s\n", + purple_conversation_get_name(conv)); return; - gtkconv->u.im->anim = anim; - - if (err) { - purple_debug(PURPLE_DEBUG_ERROR, "gtkconv", - "Buddy icon error: %s\n", err->message); - g_error_free(err); } if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) {