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;