b=424333; BadAlloc under X when viewing extremely large images; r=joe
authorVladimir Vukicevic <vladimir@pobox.com>
Sun, 09 Nov 2008 15:39:41 -0800
changeset 21537 b4fce456d38caa7ae1c5d57823590a1c193461d4
parent 21536 b5dc0e84995938789ec027d5d443efde9909f905
child 21538 7ecd487ffe0c6fe1c4094b4048dc9221963226e6
push id3564
push uservladimir@mozilla.com
push dateSun, 09 Nov 2008 23:43:55 +0000
treeherdermozilla-central@d1baec088ee0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs424333
milestone1.9.1b2pre
b=424333; BadAlloc under X when viewing extremely large images; r=joe
gfx/thebes/src/cairo-xlib-utils.c
gfx/thebes/src/gfxPlatformGtk.cpp
--- a/gfx/thebes/src/cairo-xlib-utils.c
+++ b/gfx/thebes/src/cairo-xlib-utils.c
@@ -54,16 +54,18 @@
 
 #if 0
 #include <stdio.h>
 #define CAIRO_GDK_DRAWING_NOTE(m) fprintf(stderr, m)
 #else
 #define CAIRO_GDK_DRAWING_NOTE(m) do {} while (0)
 #endif
 
+#define GDK_PIXMAP_SIZE_MAX 32767
+
 static cairo_user_data_key_t pixmap_free_key;
 static void pixmap_free_func (void *data)
 {
     GdkPixmap *pixmap = (GdkPixmap *) data;
     g_object_unref(pixmap);
 }
 
 /* We have three basic strategies available:
@@ -313,16 +315,20 @@ static cairo_bool_t
 }
 
 static cairo_surface_t *
 _create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height,
                            cairo_gdk_drawing_support_t capabilities)
 {
     cairo_surface_t *result = NULL;
 
+    if (width >= GDK_PIXMAP_SIZE_MAX ||
+        height >= GDK_PIXMAP_SIZE_MAX)
+        return NULL;
+
     /* base the temp surface on the *screen* surface, not any intermediate
      * group surface, because the screen surface is more likely to have
      * characteristics that the xlib-using code is likely to be happy with */
     cairo_surface_t *target = cairo_get_target (cr);
     Drawable target_drawable = cairo_xlib_surface_get_drawable (target);
     GdkDrawable *gdk_target_drawable = GDK_DRAWABLE(gdk_xid_table_lookup(target_drawable));
 
     GdkPixmap *pixmap = NULL;
--- a/gfx/thebes/src/gfxPlatformGtk.cpp
+++ b/gfx/thebes/src/gfxPlatformGtk.cpp
@@ -73,16 +73,18 @@
 #endif
 
 #include <fontconfig/fontconfig.h>
 
 #include "nsMathUtils.h"
 
 #include "lcms.h"
 
+#define GDK_PIXMAP_SIZE_MAX 32767
+
 #ifndef MOZ_PANGO
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #endif
 
 double gfxPlatformGtk::sDPI = -1.0;
 gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
 
@@ -144,16 +146,21 @@ gfxPlatformGtk::~gfxPlatformGtk()
 #endif
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size,
                                        gfxASurface::gfxImageFormat imageFormat)
 {
     nsRefPtr<gfxASurface> newSurface = nsnull;
+    PRBool sizeOk = PR_TRUE;
+
+    if (size.width >= GDK_PIXMAP_SIZE_MAX ||
+        size.height >= GDK_PIXMAP_SIZE_MAX)
+        sizeOk = PR_FALSE;
 
 #ifdef MOZ_X11
     int glitzf;
     int xrenderFormatID;
     switch (imageFormat) {
         case gfxASurface::ImageFormatARGB32:
             glitzf = 0; // GLITZ_STANDARD_ARGB32;
             xrenderFormatID = PictStandardARGB32;
@@ -180,17 +187,17 @@ gfxPlatformGtk::CreateOffscreenSurface(c
     Display* display = GDK_DISPLAY();
     if (!display)
         return nsnull;
 
     GdkPixmap* pixmap = nsnull;
     XRenderPictFormat* xrenderFormat =
         XRenderFindStandardFormat(display, xrenderFormatID);
 
-    if (xrenderFormat) {
+    if (xrenderFormat && sizeOk) {
         pixmap = gdk_pixmap_new(nsnull, size.width, size.height,
                                 xrenderFormat->depth);
 
         if (pixmap) {
             gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap), nsnull);
             newSurface = new gfxXlibSurface(display,
                                             GDK_PIXMAP_XID(GDK_DRAWABLE(pixmap)),
                                             xrenderFormat,
@@ -206,28 +213,31 @@ gfxPlatformGtk::CreateOffscreenSurface(c
             // Ignore and let's fall back to image surfaces.
             newSurface = nsnull;
         }
 
         // always unref; SetGdkDrawable takes its own ref
         if (pixmap)
             g_object_unref(pixmap);
     }
-
-    if (!newSurface) {
-        // We don't have Render or we couldn't create an xlib surface for
-        // whatever reason; fall back to image surface for the data.
-        newSurface = new gfxImageSurface(gfxIntSize(size.width, size.height), imageFormat);
-    }
 #endif
 
 #ifdef MOZ_DFB
-    newSurface = new gfxDirectFBSurface(size, imageFormat);
+    if (sizeOk)
+        newSurface = new gfxDirectFBSurface(size, imageFormat);
 #endif
 
+
+    if (!newSurface) {
+        // We couldn't create a native surface for whatever reason;
+        // e.g., no RENDER, bad size, etc.
+        // Fall back to image surface for the data.
+        newSurface = new gfxImageSurface(gfxIntSize(size.width, size.height), imageFormat);
+    }
+
     if (newSurface) {
         gfxContext tmpCtx(newSurface);
         tmpCtx.SetOperator(gfxContext::OPERATOR_CLEAR);
         tmpCtx.Paint();
     }
 
     return newSurface.forget();
 }