From: Sung-jae Park Date: Thu, 7 May 2015 06:27:50 +0000 (+0900) Subject: Protect from invalid vwin_info accessing X-Git-Tag: accepted/tizen/mobile/20150515.060242^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F62%2F39162%2F1;p=apps%2Fnative%2Fwidget%2Fwidget.git Protect from invalid vwin_info accessing In some weird cases, if anyone tries to access vwin info object, try to check its state first. if the state indicates unknown, stop and return. [model] Redwood,Kiran,B3(Wearable) [binary_type] AP [customer] Docomo/Orange/ATT/Open [issue#] N/A [problem] [cause] [solution] [team] HomeTF [request] [horizontal_expansion] Change-Id: Ibb212ec67f1c9f189c498679d591a3d1310c78dd Signed-off-by: Sung-jae Park --- diff --git a/include/binder.h b/include/binder.h index 8496778..6683ca5 100644 --- a/include/binder.h +++ b/include/binder.h @@ -19,6 +19,10 @@ * Abstracted Data Type of Virtual Window */ typedef struct virtual_window_info { + enum _state { + VWIN_INFO_CREATED = 0x00beef00, + VWIN_INFO_DESTROYED = 0x00dead00 + } state; char *id; /**< Identification */ widget_buffer_h handle; /**< Livebox buffer handle */ enum win_type { diff --git a/src/binder.c b/src/binder.c index 09fac0e..d586f9f 100644 --- a/src/binder.c +++ b/src/binder.c @@ -389,6 +389,7 @@ static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap) if (info->deleted && info->resource_cnt == 0) { DbgPrint("Destroy buffer handle\n"); + info->state = VWIN_INFO_DESTROYED; widget_destroy_buffer(info->handle); free(info->resource_array); free(info->id); @@ -489,6 +490,7 @@ static void free_fb(void *data, void *ptr) } if (info->deleted) { + info->state = VWIN_INFO_DESTROYED; widget_destroy_buffer(info->handle); free(info->resource_array); free(info->id); diff --git a/src/virtual_window.c b/src/virtual_window.c index 664690d..66f42ed 100644 --- a/src/virtual_window.c +++ b/src/virtual_window.c @@ -45,6 +45,7 @@ #define PUBLIC __attribute__((visibility("default"))) #define WIDGET_WIN_TAG "dynamic,box,win" +#define WIN_INFO_TAG "dynamic,box,info" #define WIDGET_DEFAULT_WIDTH 1 #define WIDGET_DEFAULT_HEIGHT 1 @@ -119,7 +120,7 @@ static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_ unsigned int flags = 0; double timestamp; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { /* Just ignore this event */ return 0; } @@ -574,7 +575,7 @@ static void pre_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } @@ -601,7 +602,7 @@ static void post_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } @@ -657,7 +658,7 @@ static int pre_orientation_cb(const char *id, void *data) int orientation; /* Try provider_app first */ - if (!id) { + if (!info || info->state != VWIN_INFO_CREATED || !id) { return WIDGET_ERROR_INVALID_PARAMETER; } @@ -684,6 +685,10 @@ static int pre_destroy_cb(const char *id, void *data) vwin_info_t info = data; const char *path = NULL; + if (!info || info->state != VWIN_INFO_CREATED) { + return WIDGET_ERROR_INVALID_PARAMETER; + } + if (id) { path = widget_util_uri_to_path(id); @@ -708,7 +713,7 @@ static void ecore_evas_free_cb(Ecore_Evas *ee) { vwin_info_t info; - info = ecore_evas_data_get(ee, "dynamic,box,info"); + info = ecore_evas_data_get(ee, WIN_INFO_TAG); if (!info) { DbgPrint("Info is not valid\n"); return; @@ -751,9 +756,12 @@ PUBLIC Evas *widget_get_evas(const char *id) return NULL; } + info->state = VWIN_INFO_CREATED; + info->id = strdup(id); if (!info->id) { ErrPrint("Heap: %d\n", errno); + info->state = VWIN_INFO_DESTROYED; free(info); return NULL; } @@ -773,6 +781,7 @@ PUBLIC Evas *widget_get_evas(const char *id) if (!info->handle) { ErrPrint("Failed to create a widget buffer\n"); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; @@ -788,12 +797,13 @@ PUBLIC Evas *widget_get_evas(const char *id) if (!info->ee) { ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h); widget_destroy_buffer(info->handle); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; } - ecore_evas_data_set(info->ee, "dynamic,box,info", info); + ecore_evas_data_set(info->ee, WIN_INFO_TAG, info); /** * @note diff --git a/src/virtual_window_wayland.c b/src/virtual_window_wayland.c index 1fab6d3..5bd2c80 100644 --- a/src/virtual_window_wayland.c +++ b/src/virtual_window_wayland.c @@ -24,6 +24,7 @@ #include #include +#include "binder.h" #include "widget.h" #include "debug.h" @@ -36,41 +37,6 @@ #define WIDGET_DEFAULT_HEIGHT 1 #define GL_ENGINE "opengl_x11" -static struct static_info { - Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data); - Ecore_Evas *(*alloc_canvas_with_stride)(int w, int h, void *(*a)(void *data, int size, int *stride, int *bpp), void (*f)(void *data, void *ptr), void *data); - Ecore_Evas *(*alloc_canvas_with_pixmap)(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h, Ecore_X_Pixmap (*alloc_cb)(void *data, Ecore_X_Window parent, int w, int h, int depth), void (*free_cb)(void *data, Ecore_X_Pixmap pixmap), void *data); -} s_info = { - .alloc_canvas = NULL, - .alloc_canvas_with_stride = NULL, - .alloc_canvas_with_pixmap = NULL, -}; - -/** - * @brief - * Abstracted Data Type of Virtual Window - */ -typedef struct virtual_window_info { - char *id; /**< Identification */ - widget_buffer_h handle; /**< Livebox buffer handle */ - enum win_type { - VWIN_SW_BUF = 0x00, /**< S/W buffer */ - VWIN_GEM = 0x01, /**< GEM buffer */ - VWIN_PIXMAP = 0x02, /**< PIXMAP */ - VWIN_ERROR = 0x03 /**< Unknown */ - } type; - Ecore_Evas *ee; - Evas *e; - int is_gbar; - int deleted; - int w; - int h; - unsigned int *resource_array; - int resource_cnt; - - int pressed; -} *vwin_info_t; - static inline Evas_Object *get_highlighted_object(Evas_Object *obj) { Evas_Object *o, *ho; @@ -82,6 +48,50 @@ static inline Evas_Object *get_highlighted_object(Evas_Object *obj) return ho; } +static inline void apply_orientation(int degree, int *x, int *y, int width, int height, input_event_source_e source) +{ + int _x; + int _y; + int _angle; + + if (source == INPUT_EVENT_SOURCE_VIEWER) { + /* Already rotated */ + return; + } + + _x = *x; + _y = *y; + + switch (degree) { + case 0: + return; + case 90: + *x = _y; + *y = width - _x; + return; + case 180: + *x = width - _x; + *y = height - _y; + return; + case 270: + *x = height - _y; + *y = _x; + return; + default: + /** + * @FIXME + * This rotation formular is not work correctly. + * The pointer should be rotated by other way. + * This is not what we want. + */ + _angle = degree; + + *x = (double)_x * cos((double)_angle) - (double)_y * sin((double)_angle); + *y = (double)_x * sin((double)_angle) + (double)_y * cos((double)_angle); + return; + } +} + /*! * \note * Every user event (mouse) on the buffer will be passed via this event callback @@ -171,6 +181,7 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ evas_event_feed_mouse_out(info->e, timestamp, NULL); break; case WIDGET_BUFFER_EVENT_DOWN: + apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); if (info->pressed) { ErrPrint("MOUSE UP is not called\n"); ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); @@ -198,6 +209,7 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp); break; case WIDGET_BUFFER_EVENT_MOVE: + apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); /** * @note * Calculate the event occurred X & Y on the buffer @@ -205,6 +217,7 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); break; case WIDGET_BUFFER_EVENT_UP: + apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source); evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL); evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); info->pressed = 0; @@ -459,18 +472,6 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ break; } - key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret); - if (key_symbol) { - char *key_name; - char *key_string; - - key_string = XKeysymToString(*key_symbol); - key_name = XKeysymToString(*key_symbol); - DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name); - XFree(key_symbol); - XFree(key_name); - XFree(key_string); - } ret = WIDGET_KEY_STATUS_ERROR; break; case WIDGET_BUFFER_EVENT_KEY_UP: @@ -480,18 +481,6 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ break; } - key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret); - if (key_symbol) { - char *key_name; - char *key_string; - - key_string = XKeysymToString(*key_symbol); - key_name = XKeysymToString(*key_symbol); - DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name); - XFree(key_symbol); - XFree(key_name); - XFree(key_string); - } ret = WIDGET_KEY_STATUS_ERROR; break; case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN: @@ -501,18 +490,6 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ break; } - key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret); - if (key_symbol) { - char *key_name; - char *key_string; - - key_string = XKeysymToString(*key_symbol); - key_name = XKeysymToString(*key_symbol); - DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name); - XFree(key_symbol); - XFree(key_name); - XFree(key_string); - } ret = WIDGET_KEY_STATUS_ERROR; break; case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT: @@ -522,18 +499,6 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ break; } - key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret); - if (key_symbol) { - char *key_name; - char *key_string; - - key_string = XKeysymToString(*key_symbol); - key_name = XKeysymToString(*key_symbol); - DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name); - XFree(key_symbol); - XFree(key_name); - XFree(key_string); - } ret = WIDGET_KEY_STATUS_ERROR; break; default: @@ -544,88 +509,11 @@ static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_ return ret; } -static void *alloc_fb(void *data, int size) -{ - vwin_info_t info = data; - void *buffer; - - if (info->ee) { - ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h); - DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info); - } - - if (!info->handle) { - ErrPrint("Failed to create a buffer\n"); - return NULL; - } - - if (widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) { - ErrPrint("Failed to acquire buffer\n"); - return NULL; - } - - /** - * If it supports the H/W accelerated buffer, - * Use it. - */ - if (widget_support_hw_buffer(info->handle)) { - if (widget_create_hw_buffer(info->handle) == 0) { - buffer = widget_buffer_hw_buffer(info->handle); - if (buffer) { - DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h); - info->type = VWIN_GEM; - return buffer; - } - } - - ErrPrint("Failed to allocate HW Accelerated buffer\n"); - } - - /** - * Or use the buffer of a S/W backend. - */ - buffer = widget_ref_buffer(info->handle); - DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h); - info->type = VWIN_SW_BUF; - return buffer; -} - -static void free_fb(void *data, void *ptr) -{ - vwin_info_t info = data; - - if (!info->handle) { - return; - } - - if (info->type == VWIN_GEM) { - if (widget_destroy_hw_buffer(info->handle) == 0) { - DbgPrint("HW Accelerated buffer is destroyed\n"); - } - } else if (info->type == VWIN_SW_BUF) { - DbgPrint("SW buffer is destroyed, %p\n", info); - widget_unref_buffer(ptr); - } else if (info->type == VWIN_PIXMAP) { - ErrPrint("Unable to reach to here\n"); - } - - if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) { - ErrPrint("Failed to release buffer\n"); - } - - if (info->deleted) { - widget_destroy_buffer(info->handle); - free(info->resource_array); - free(info->id); - free(info); - } -} - static void pre_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } @@ -652,7 +540,7 @@ static void post_render_cb(void *data, Evas *e, void *event_info) { vwin_info_t info = data; - if (!info->handle) { + if (!info || info->state != VWIN_INFO_CREATED || !info->handle) { return; } @@ -674,41 +562,61 @@ static void post_render_cb(void *data, Evas *e, void *event_info) if (info->type == VWIN_GEM) { widget_buffer_post_render(info->handle); } else if (info->type == VWIN_PIXMAP) { - int idx; - unsigned int front_resource_id; + /** + * TODO + */ + ErrPrint("NOT SUPPORTED\n"); + } else if (info->type == VWIN_SW_BUF) { + widget_viewer_sync_buffer(info->handle); + } +} - front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee); +static int pre_orientation_cb(const char *id, void *data) +{ + vwin_info_t info = data; + const char *path; + int orientation; - for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) { - if (front_resource_id == info->resource_array[idx]) { - /** - */ - widget_send_updated_by_idx(info->handle, idx); - break; - } - } + /* Try provider_app first */ + if (!info || info->state != VWIN_INFO_CREATED || !id) { + return WIDGET_ERROR_INVALID_PARAMETER; + } - if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) { - /* Send updated event for PRIMARY BUFFER */ - if (front_resource_id == widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)) { - widget_send_updated_by_idx(info->handle, WIDGET_PRIMARY_BUFFER); - } else { - DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)); - } - } - } else if (info->type == VWIN_SW_BUF) { - widget_viewer_sync_buffer(info->handle); + path = widget_util_uri_to_path(id); + if (path && strcmp(info->id, path)) { + /* Skip */ + DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id); + return WIDGET_ERROR_INVALID_PARAMETER; + } + + DbgPrint("Pre orientation event callback is called [%s]\n", id); + orientation = widget_get_orientation(path); + if (orientation < 0) { + ErrPrint("Failed to get orientation: %X\n", orientation); + } else { + info->orientation = orientation; } + + return WIDGET_ERROR_NONE; } static void pre_destroy_cb(const char *id, void *data) { vwin_info_t info = data; + const char *path = NULL; - if (id && strcmp(info->id, widget_util_uri_to_path(id))) { - /* Skip */ - DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id); - return; + if (!info || info->state != VWIN_INFO_CREATED) { + return WIDGET_ERROR_INVALID_PARAMETER; + } + + if (id) { + path = widget_util_uri_to_path(id); + + if (path && strcmp(info->id, path)) { + /* Skip */ + DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id); + return WIDGET_ERROR_INVALID_PARAMETER; + } } DbgPrint("Pre destroy event callback is called [%s]\n", id); @@ -717,6 +625,8 @@ static void pre_destroy_cb(const char *id, void *data) DbgPrint("Toggle manual render mode to prevent from unwanted rendering"); ecore_evas_manual_render_set(info->ee, EINA_TRUE); } + + return WIDGET_ERROR_NONE; } static void ecore_evas_free_cb(Ecore_Evas *ee) @@ -747,8 +657,7 @@ PUBLIC Evas *widget_get_evas(const char *id) #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */ { vwin_info_t info; - Evas_Object *rect; - const char *engine; + int orientation; /** * @TODO @@ -756,30 +665,6 @@ PUBLIC Evas *widget_get_evas(const char *id) * this function should returns ERROR. */ - if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) { - /* - s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new"); - if (!s_info.alloc_canvas_with_pixmap) { - DbgPrint("pixmap_allocfunc_new is not found\n"); - } - */ - - s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new"); - if (!s_info.alloc_canvas_with_stride) { - DbgPrint("allocfunc_with_stirde_new is not found\n"); - } - - s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new"); - if (!s_info.alloc_canvas) { - ErrPrint("allocfunc_new is not found\n"); - } - - if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) { - ErrPrint("No way to allocate canvas\n"); - return NULL; - } - } - if (!id) { ErrPrint("Invalid parameter\n"); return NULL; @@ -791,9 +676,12 @@ PUBLIC Evas *widget_get_evas(const char *id) return NULL; } + info->state = VWIN_INFO_CREATED; + info->id = strdup(id); if (!info->id) { ErrPrint("Heap: %d\n", errno); + info->state = VWIN_INFO_DESTROYED; free(info); return NULL; } @@ -808,11 +696,12 @@ PUBLIC Evas *widget_get_evas(const char *id) * Acquire a buffer for canvas. */ info->handle = widget_create_buffer(info->id, info->is_gbar, - (widget_conf_auto_align() || !s_info.alloc_canvas_with_stride), + widget_conf_auto_align(), event_handler_cb, info); if (!info->handle) { ErrPrint("Failed to create a widget buffer\n"); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; @@ -824,28 +713,11 @@ PUBLIC Evas *widget_get_evas(const char *id) info->w = WIDGET_DEFAULT_WIDTH; info->h = WIDGET_DEFAULT_HEIGHT; - engine = elm_config_preferred_engine_get(); - DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE); - if (engine && !strcmp(engine, GL_ENGINE)) { - if (s_info.alloc_canvas_with_pixmap) { - info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info); - if (!info->ee) { - ErrPrint("Unable to create a ee for pixmap\n"); - } - } - } - - if (!info->ee) { - if (!widget_conf_auto_align() && s_info.alloc_canvas_with_stride) { - info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info); - } else if (s_info.alloc_canvas) { - info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info); - } - } - + info->ee = binder_ecore_evas_new(info); if (!info->ee) { ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h); widget_destroy_buffer(info->handle); + info->state = VWIN_INFO_DESTROYED; free(info->id); free(info); return NULL; @@ -877,6 +749,14 @@ PUBLIC Evas *widget_get_evas(const char *id) evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info); widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info); + widget_add_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, pre_orientation_cb, info); + + orientation = widget_get_orientation(info->id); + if (orientation < 0) { + ErrPrint("Failed to get orientation[%s]: %X\n", info->id, orientation); + } else { + info->orientation = orientation; + } return info->e; }