wl_scaler: fix memory corruption 23/39123/1
authorBoram Park <boram1288.park@samsung.com>
Fri, 8 May 2015 08:27:55 +0000 (17:27 +0900)
committerBoram Park <boram1288.park@samsung.com>
Sat, 9 May 2015 01:11:06 +0000 (10:11 +0900)
Change-Id: I9b1637ac6e6d94e8b0382ad4dccd3499d2bb7dcf

src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/bin/e_pixmap.c
src/modules/wl_desktop_shell/e_scaler.c

index 55e498f..a1b116e 100644 (file)
@@ -110,8 +110,8 @@ _e_comp_wl_map_size_cal_from_buffer(E_Client *ec)
 
    if (!ec->comp_data->buffer_ref.buffer)
      {
-        vp->width_from_buffer = 0;
-        vp->height_from_buffer = 0;
+        ec->comp_data->width_from_buffer = 0;
+        ec->comp_data->height_from_buffer = 0;
         return;
      }
 
@@ -130,8 +130,8 @@ _e_comp_wl_map_size_cal_from_buffer(E_Client *ec)
         break;
      }
 
-   vp->width_from_buffer = width;
-   vp->height_from_buffer = height;
+   ec->comp_data->width_from_buffer = width;
+   ec->comp_data->height_from_buffer = height;
 }
 
 static void
@@ -140,13 +140,13 @@ _e_comp_wl_map_size_cal_from_viewport(E_Client *ec)
    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
    int32_t width, height;
 
-   width = vp->width_from_buffer;
-   height = vp->height_from_buffer;
+   width = ec->comp_data->width_from_buffer;
+   height = ec->comp_data->height_from_buffer;
 
    if (width != 0 && vp->surface.width != -1)
      {
-        vp->width_from_viewport = vp->surface.width;
-        vp->height_from_viewport = vp->surface.height;
+        ec->comp_data->width_from_viewport = vp->surface.width;
+        ec->comp_data->height_from_viewport = vp->surface.height;
         return;
      }
 
@@ -154,13 +154,13 @@ _e_comp_wl_map_size_cal_from_viewport(E_Client *ec)
      {
         int32_t w = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_width);
         int32_t h = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_height);
-        vp->width_from_viewport = w ?: 1;
-        vp->height_from_viewport = h ?: 1;
+        ec->comp_data->width_from_viewport = w ?: 1;
+        ec->comp_data->height_from_viewport = h ?: 1;
         return;
      }
 
-   vp->width_from_viewport = width;
-   vp->height_from_viewport = height;
+   ec->comp_data->width_from_viewport = width;
+   ec->comp_data->height_from_viewport = height;
 }
 
 static void
@@ -211,14 +211,14 @@ _e_comp_wl_map_apply(E_Client *ec)
 
    evas_map_util_points_populate_from_geometry(map,
                                                ec->x, ec->y,
-                                               vp->width_from_viewport, vp->height_from_viewport, 0);
+                                               ec->comp_data->width_from_viewport, ec->comp_data->height_from_viewport, 0);
 
    if (vp->buffer.src_width == wl_fixed_from_int(-1))
      {
         x1 = 0.0;
         y1 = 0.0;
-        x2 = vp->width_from_buffer;
-        y2 = vp->height_from_buffer;
+        x2 = ec->comp_data->width_from_buffer;
+        y2 = ec->comp_data->height_from_buffer;
      }
    else
      {
@@ -228,22 +228,22 @@ _e_comp_wl_map_apply(E_Client *ec)
         y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height);
      }
 
-   _e_comp_wl_map_transform(vp->width_from_buffer, vp->height_from_buffer,
+   _e_comp_wl_map_transform(ec->comp_data->width_from_buffer, ec->comp_data->height_from_buffer,
                             vp->buffer.transform, vp->buffer.scale,
                             x1, y1, &x, &y);
    evas_map_point_image_uv_set(map, 0, x, y);
 
-   _e_comp_wl_map_transform(vp->width_from_buffer, vp->height_from_buffer,
+   _e_comp_wl_map_transform(ec->comp_data->width_from_buffer, ec->comp_data->height_from_buffer,
                             vp->buffer.transform, vp->buffer.scale,
                             x2, y1, &x, &y);
    evas_map_point_image_uv_set(map, 1, x, y);
 
-   _e_comp_wl_map_transform(vp->width_from_buffer, vp->height_from_buffer,
+   _e_comp_wl_map_transform(ec->comp_data->width_from_buffer, ec->comp_data->height_from_buffer,
                             vp->buffer.transform, vp->buffer.scale,
                             x2, y2, &x, &y);
    evas_map_point_image_uv_set(map, 2, x, y);
 
-   _e_comp_wl_map_transform(vp->width_from_buffer, vp->height_from_buffer,
+   _e_comp_wl_map_transform(ec->comp_data->width_from_buffer, ec->comp_data->height_from_buffer,
                             vp->buffer.transform, vp->buffer.scale,
                             x1, y2, &x, &y);
    evas_map_point_image_uv_set(map, 3, x, y);
@@ -2316,11 +2316,9 @@ _e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
    /* eina_hash_add(clients_win_hash, &win, ec); */
    e_hints_client_list_set();
 
-   E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ec->pixmap);
-   struct wl_resource *wl_resource = cdata->wl_surface;
-   ec->comp_data->scaler = cdata->scaler;
    e_pixmap_cdata_set(ec->pixmap, ec->comp_data);
-   _e_comp_wl_surface_cb_commit(NULL, wl_resource);
+   if (ec->comp_data->wl_surface)
+     _e_comp_wl_surface_cb_commit(NULL, ec->comp_data->wl_surface);
 }
 
 static void
index 2ce5488..4429ee7 100644 (file)
@@ -89,14 +89,6 @@ struct _E_Comp_Wl_Buffer_Viewport {
      } surface;
 
    int changed;
-
-   /* before applying viewport */
-   int width_from_buffer;
-   int height_from_buffer;
-
-   /* after applying viewport */
-   int width_from_viewport;
-   int height_from_viewport;
 };
 
 struct _E_Comp_Wl_Surface_State
@@ -305,6 +297,14 @@ struct _E_Comp_Wl_Client_Data
         E_Comp_Wl_Buffer_Viewport buffer_viewport;
      } scaler;
 
+   /* before applying viewport */
+   int width_from_buffer;
+   int height_from_buffer;
+
+   /* after applying viewport */
+   int width_from_viewport;
+   int height_from_viewport;
+
    Eina_Bool keep_buffer : 1;
    Eina_Bool mapped : 1;
    Eina_Bool change_icon : 1;
index b3228be..800b910 100644 (file)
@@ -36,9 +36,10 @@ struct _E_Pixmap
    struct wl_listener buffer_destroy_listener;
    void *data;
    Eina_Rectangle opaque;
-#endif
 
-   E_Comp_Client_Data *cdata;
+   E_Comp_Wl_Client_Data *cdata;
+   Eina_Bool own_cdata : 1;
+#endif
 
    Eina_Bool usable : 1;
    Eina_Bool dirty : 1;
@@ -85,6 +86,12 @@ _e_pixmap_clear(E_Pixmap *cp, Eina_Bool cache)
 
         e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
 
+        if (cp->own_cdata)
+          {
+             free (cp->cdata);
+             cp->own_cdata = EINA_FALSE;
+          }
+
         (void)cache;
 #endif
         break;
@@ -143,9 +150,13 @@ _e_pixmap_new(E_Pixmap_Type type)
    cp->refcount = 1;
    cp->dirty = 1;
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-   cp->cdata = calloc(1, sizeof(E_Comp_Wl_Client_Data));
-#else
-   cp->cdata = calloc(1, sizeof(E_Comp_X_Client_Data));
+   cp->own_cdata = EINA_TRUE;
+   cp->cdata = E_NEW(E_Comp_Wl_Client_Data, 1);
+   cp->cdata->pending.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+   cp->cdata->pending.buffer_viewport.buffer.scale = 1;
+   cp->cdata->pending.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
+   cp->cdata->pending.buffer_viewport.surface.width = -1;
+   cp->cdata->pending.buffer_viewport.changed = 0;
 #endif
    return cp;
 }
@@ -961,14 +972,34 @@ EAPI E_Comp_Client_Data *
 e_pixmap_cdata_get(E_Pixmap *cp)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(cp, NULL);
+
+#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
    return (E_Comp_Client_Data*)cp->cdata;
+#else
+   return NULL;
+#endif
 }
 
 EAPI void
 e_pixmap_cdata_set(E_Pixmap *cp, E_Comp_Client_Data *cdata)
 {
+#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
+   E_Comp_Wl_Client_Data *cd = (E_Comp_Wl_Client_Data*)cdata;
+
    EINA_SAFETY_ON_NULL_RETURN(cp);
+   EINA_SAFETY_ON_NULL_RETURN(cp->cdata);
    EINA_SAFETY_ON_NULL_RETURN(cdata);
-   free (cp->cdata);
-   cp->cdata = cdata;
+
+   if (cp->own_cdata)
+     {
+        cd->wl_surface = cp->cdata->wl_surface;
+        cd->scaler.viewport = cp->cdata->scaler.viewport;
+        cd->pending.buffer_viewport = cp->cdata->pending.buffer_viewport;
+
+        free (cp->cdata);
+        cp->own_cdata = EINA_FALSE;
+     }
+
+   cp->cdata = cd;
+#endif
 }
index e0aabe9..3c4ae83 100644 (file)
@@ -6,8 +6,10 @@
 static void
 _e_viewport_destroy(struct wl_resource *resource)
 {
-   E_Comp_Client_Data *cdata = wl_resource_get_user_data(resource);
+   E_Pixmap *ep = wl_resource_get_user_data(resource);
+   E_Comp_Client_Data *cdata = e_pixmap_cdata_get(ep);
 
+   EINA_SAFETY_ON_NULL_RETURN(cdata);
    EINA_SAFETY_ON_NULL_RETURN(cdata->scaler.viewport);
 
    cdata->scaler.viewport = NULL;
@@ -32,8 +34,10 @@ _e_viewport_cb_set(struct wl_client *client EINA_UNUSED,
                    int32_t dst_width,
                    int32_t dst_height)
 {
-   E_Comp_Client_Data *cdata = wl_resource_get_user_data(resource);
+   E_Pixmap *ep = wl_resource_get_user_data(resource);
+   E_Comp_Client_Data *cdata = e_pixmap_cdata_get(ep);
 
+   EINA_SAFETY_ON_NULL_RETURN(cdata);
    EINA_SAFETY_ON_NULL_RETURN(cdata->scaler.viewport);
 
    if (wl_fixed_to_double(src_width) < 0 || wl_fixed_to_double(src_height) < 0)
@@ -72,8 +76,10 @@ _e_viewport_cb_set_source(struct wl_client *client EINA_UNUSED,
                           wl_fixed_t src_width,
                           wl_fixed_t src_height)
 {
-   E_Comp_Client_Data *cdata = wl_resource_get_user_data(resource);
+   E_Pixmap *ep = wl_resource_get_user_data(resource);
+   E_Comp_Client_Data *cdata = e_pixmap_cdata_get(ep);
 
+   EINA_SAFETY_ON_NULL_RETURN(cdata);
    EINA_SAFETY_ON_NULL_RETURN(cdata->scaler.viewport);
 
    if (src_width == wl_fixed_from_int(-1) && src_height == wl_fixed_from_int(-1))
@@ -107,8 +113,10 @@ _e_viewport_cb_set_destination(struct wl_client *client EINA_UNUSED,
                                int32_t dst_width,
                                int32_t dst_height)
 {
-   E_Comp_Client_Data *cdata = wl_resource_get_user_data(resource);
+   E_Pixmap *ep = wl_resource_get_user_data(resource);
+   E_Comp_Client_Data *cdata = e_pixmap_cdata_get(ep);
 
+   EINA_SAFETY_ON_NULL_RETURN(cdata);
    EINA_SAFETY_ON_NULL_RETURN(cdata->scaler.viewport);
 
    if (dst_width == -1 && dst_height == -1)
@@ -173,7 +181,7 @@ _e_scaler_cb_get_viewport(struct wl_client *client EINA_UNUSED, struct wl_resour
      }
 
    cdata->scaler.viewport = res;
-   wl_resource_set_implementation(res, &_e_viewport_interface, cdata, _e_viewport_destroy);
+   wl_resource_set_implementation(res, &_e_viewport_interface, ep, _e_viewport_destroy);
 }
 
 static const struct wl_scaler_interface _e_scaler_interface =
@@ -185,15 +193,8 @@ static const struct wl_scaler_interface _e_scaler_interface =
 static void
 _e_scaler_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
-   E_Comp_Data *cdata;
    struct wl_resource *res;
 
-   if (!(cdata = data))
-     {
-        wl_client_post_no_memory(client);
-        return;
-     }
-
    if (!(res = wl_resource_create(client, &wl_scaler_interface, MIN(version, 2), id)))
      {
         ERR("Could not create scaler resource: %m");
@@ -201,7 +202,7 @@ _e_scaler_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32
         return;
      }
 
-   wl_resource_set_implementation(res, &_e_scaler_interface, cdata, NULL);
+   wl_resource_set_implementation(res, &_e_scaler_interface, NULL, NULL);
 }
 
 Eina_Bool