commit f55d32f

Michael Forney  ·  2013-12-07 07:54:33 +0000 UTC
parent 1f66aea
surface: Set surface size to 0 when NULL buffer is attached

This fixes a NULL pointer dereference when a damaged buffer is
destroyed, and then the surface is repainted.
2 files changed,  +44, -34
+43, -34
  1@@ -31,6 +31,37 @@
  2 #include <stdio.h>
  3 #include <wld/wld.h>
  4 
  5+static void set_size(struct swc_surface * surface,
  6+                     uint32_t width, uint32_t height)
  7+{
  8+    /* Check if the surface was resized. */
  9+    if (width != surface->geometry.width || height != surface->geometry.height)
 10+    {
 11+        struct swc_surface_event_data data = {
 12+            .surface = surface,
 13+            .resize = {
 14+                .old_width = surface->geometry.width,
 15+                .old_height = surface->geometry.height,
 16+                .new_width = width,
 17+                .new_height = height
 18+            }
 19+        };
 20+
 21+        surface->geometry.width = width;
 22+        surface->geometry.height = height;
 23+
 24+        pixman_region32_intersect_rect
 25+            (&surface->state.opaque, &surface->state.opaque,
 26+             0, 0, width, height);
 27+        pixman_region32_intersect_rect
 28+            (&surface->state.damage, &surface->state.damage,
 29+             0, 0, width, height);
 30+
 31+        swc_send_event(&surface->event_signal,
 32+                       SWC_SURFACE_EVENT_TYPE_RESIZE, &data);
 33+    }
 34+}
 35+
 36 /**
 37  * Removes a buffer from a surface state.
 38  */
 39@@ -40,12 +71,21 @@ static void handle_buffer_destroy(struct wl_listener * listener, void * data)
 40 
 41     state = CONTAINER_OF(listener, typeof(*state), buffer_destroy_listener);
 42     state->buffer = NULL;
 43+
 44+    if (state->current)
 45+    {
 46+        struct swc_surface * surface;
 47+
 48+        surface = CONTAINER_OF(state, typeof(*surface), state);
 49+        set_size(surface, 0, 0);
 50+    }
 51 }
 52 
 53-static void state_initialize(struct swc_surface_state * state)
 54+static void state_initialize(struct swc_surface_state * state, bool current)
 55 {
 56     state->buffer = NULL;
 57     state->buffer_destroy_listener.notify = &handle_buffer_destroy;
 58+    state->current = current;
 59 
 60     pixman_region32_init(&state->damage);
 61     pixman_region32_init(&state->opaque);
 62@@ -104,37 +144,6 @@ static bool state_set_buffer(struct swc_surface_state * state,
 63     return true;
 64 }
 65 
 66-static void set_size(struct swc_surface * surface,
 67-                     uint32_t width, uint32_t height)
 68-{
 69-    /* Check if the surface was resized. */
 70-    if (width != surface->geometry.width || height != surface->geometry.height)
 71-    {
 72-        struct swc_surface_event_data data = {
 73-            .surface = surface,
 74-            .resize = {
 75-                .old_width = surface->geometry.width,
 76-                .old_height = surface->geometry.height,
 77-                .new_width = width,
 78-                .new_height = height
 79-            }
 80-        };
 81-
 82-        surface->geometry.width = width;
 83-        surface->geometry.height = height;
 84-
 85-        pixman_region32_intersect_rect
 86-            (&surface->state.opaque, &surface->state.opaque,
 87-             0, 0, width, height);
 88-        pixman_region32_intersect_rect
 89-            (&surface->state.damage, &surface->state.damage,
 90-             0, 0, width, height);
 91-
 92-        swc_send_event(&surface->event_signal,
 93-                       SWC_SURFACE_EVENT_TYPE_RESIZE, &data);
 94-    }
 95-}
 96-
 97 static void destroy(struct wl_client * client, struct wl_resource * resource)
 98 {
 99     wl_resource_destroy(resource);
100@@ -368,8 +377,8 @@ struct swc_surface * swc_surface_new(struct wl_client * client,
101     surface->class = NULL;
102     surface->class_state = NULL;
103 
104-    state_initialize(&surface->state);
105-    state_initialize(&surface->pending.state);
106+    state_initialize(&surface->state, true);
107+    state_initialize(&surface->pending.state, false);
108 
109     wl_signal_init(&surface->event_signal);
110 
+1, -0
1@@ -57,6 +57,7 @@ struct swc_surface_state
2 {
3     struct wl_resource * buffer;
4     struct wl_listener buffer_destroy_listener;
5+    bool current;
6 
7     /* The region that needs to be repainted. */
8     pixman_region32_t damage;