Bug 1293598 - clean up pointers after free inside pixman_image, r=jrmuizel, a=gchang
authorpeter chang <pchang@mozilla.com>
Tue, 09 Aug 2016 17:31:05 +0800
changeset 358135 c8073dd59c81ab7486cf713a78cc7d5bd9a4112b
parent 358134 581e2e9b9d79cbaf4e333447e5966e03b92a2eb7
child 358136 a13ac865844080391623e3bbebd847dc8c3ead83
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, gchang
bugs1293598
milestone51.0a2
Bug 1293598 - clean up pointers after free inside pixman_image, r=jrmuizel, a=gchang 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,35 @@
 #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 (void** p)
+{
+#ifdef PIXMAN_POISON
+    if (*p) {
+#endif
+        free (*p);
+#ifdef PIXMAN_POISON
+        *p = NULL;
+    }
+#endif
+}
+
 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 +159,46 @@ 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);
+		void *addr = image->gradient.stops - 1;
+		free_memory (&addr);
 	    }
 
 	    /* 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 +228,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,