Bug 1293598 - clean up pointers after free inside pixman_image, r=jrmuizel
☠☠ backed out by 2c7ba40559c6 ☠ ☠
authorpeter chang <pchang@mozilla.com>
Tue, 09 Aug 2016 17:31:05 +0800
changeset 357643 854e74094d8cf43e8a00f953e09a3068a2c18e25
parent 357642 ef7939c0332eb73be104210509dd45488f03dc3e
child 357644 d8a383370502b41992775dc4efc2501453c14170
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1293598
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1293598 - clean up pointers after free inside pixman_image, r=jrmuizel MozReview-Commit-ID: ChUb4RYUabN
gfx/cairo/libpixman/src/pixman-image.c
--- a/gfx/cairo/libpixman/src/pixman-image.c
+++ b/gfx/cairo/libpixman/src/pixman-image.c
@@ -28,16 +28,41 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 
 #include "pixman-private.h"
 
 static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
 
+/**
+ ** bug 1293598 - clean up every pointer after free to avoid
+ ** "dereferencing freed memory" problem
+ **/
+#define PIXMAN_POSION
+
+static void
+free_memory_withoffset (void** p, int offset)
+{
+#ifdef PIXMAN_POISON
+    if (*p) {
+#endif
+        free (*p + offset);
+#ifdef PIXMAN_POISON
+        *p = NULL;
+    }
+#endif
+}
+
+static void
+free_memory (void** p)
+{
+  free_memory_withoffset (p, 0);
+}
+
 static void
 gradient_property_changed (pixman_image_t *image)
 {
     gradient_t *gradient = &image->gradient;
     int n = gradient->n_stops;
     pixman_gradient_stop_t *stops = gradient->stops;
     pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
     pixman_gradient_stop_t *end = &(gradient->stops[n]);
@@ -140,42 +165,45 @@ pixman_bool_t
 
     if (common->ref_count == 0)
     {
 	if (image->common.destroy_func)
 	    image->common.destroy_func (image, image->common.destroy_data);
 
 	pixman_region32_fini (&common->clip_region);
 
-	free (common->transform);
-	free (common->filter_params);
+	free_memory (&common->transform);
+	free_memory (&common->filter_params);
 
 	if (common->alpha_map)
 	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
 
 	if (image->type == LINEAR ||
 	    image->type == RADIAL ||
 	    image->type == CONICAL)
 	{
 	    if (image->gradient.stops)
 	    {
 		/* See _pixman_init_gradient() for an explanation of the - 1 */
-		free (image->gradient.stops - 1);
+		free_memory_withoffset (&image->gradient.stops, -1);
 	    }
 
 	    /* This will trigger if someone adds a property_changed
 	     * method to the linear/radial/conical gradient overwriting
 	     * the general one.
 	     */
 	    assert (
 		image->common.property_changed == gradient_property_changed);
 	}
 
-	if (image->type == BITS && image->bits.free_me)
-	    free (image->bits.free_me);
+	if (image->type == BITS && image->bits.free_me) {
+	    free_memory (&image->bits.free_me);
+	    image->bits.bits = NULL;
+        }
+
 
 	return TRUE;
     }
 
     return FALSE;
 }
 
 pixman_image_t *
@@ -205,17 +233,17 @@ pixman_image_ref (pixman_image_t *image)
 }
 
 /* returns TRUE when the image is freed */
 PIXMAN_EXPORT pixman_bool_t
 pixman_image_unref (pixman_image_t *image)
 {
     if (_pixman_image_fini (image))
     {
-	free (image);
+	free_memory (&image);
 	return TRUE;
     }
 
     return FALSE;
 }
 
 PIXMAN_EXPORT void
 pixman_image_set_destroy_function (pixman_image_t *            image,