e_object: added OBJECT_HASH_CHECK feature. 78/44478/2
authorGwanglim Lee <gl77.lee@samsung.com>
Wed, 22 Jul 2015 11:01:58 +0000 (20:01 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Wed, 22 Jul 2015 11:54:03 +0000 (20:54 +0900)
E_Object's default magic check could trigger a use-after-free memory error.
In order to prevent it, we added OBJECT_HASH_CHECK that is checking whether
E_Object is valid or not using hash pointer.

This feature will be enabled if E_OBJECT_HASH_CHECK env var is '1'.

Change-Id: Ieb603b3cf25e63b51f8e88b86a8f678fae9e79bc

src/bin/e.h
src/bin/e_main.c
src/bin/e_object.c
src/bin/e_object.h

index f78f6fb8596224e0b6b4d15a81690e8b66036e94..7dd6c4c9ad858c7b61a7cb3c2802f8b9b8f8e1e6 100644 (file)
@@ -21,6 +21,7 @@
 #  define OBJECT_PARANOIA_CHECK
 # endif
 # define OBJECT_CHECK
+# define OBJECT_HASH_CHECK
 
 # ifndef _FILE_OFFSET_BITS
 #  define _FILE_OFFSET_BITS 64
index ee4df0fd792678790c75d4291e5c6593aec7a432..06b0dbfa8af31cfb4cc829c983e56723c961af08 100644 (file)
@@ -289,6 +289,9 @@ main(int argc, char **argv)
         _e_main_shutdown(-1);
      }
    _e_main_shutdown_push(eina_shutdown);
+#ifdef OBJECT_HASH_CHECK
+   e_object_hash_init();
+#endif
    if (!e_log_init())
      {
         e_error_message_show(_("Enlightenment could not create a logging domain!\n"));
@@ -1122,6 +1125,9 @@ _e_main_shutdown(int errcode)
      }
    for (i = (_e_main_lvl - 1); i >= 0; i--)
      (*_e_main_shutdown_func[i])();
+#ifdef OBJECT_HASH_CHECK
+   e_object_hash_shutdown();
+#endif
    if (errcode < 0) exit(errcode);
 }
 
index b8bb78e21de802830d5482d282015809fb77ef33..8379902ed04af7003de0d7ba86a47407b0f40e1a 100644 (file)
@@ -11,6 +11,11 @@ static void _e_object_segv(int sig);
 static sigjmp_buf _e_object_segv_buf;
 #endif
 
+#ifdef OBJECT_HASH_CHECK
+EAPI Eina_Bool e_obj_hash_check = EINA_FALSE;
+EAPI Eina_Hash *e_obj_hash = NULL;
+#endif
+
 /* externally accessible functions */
 EAPI void *
 e_object_alloc(int size, int type, E_Object_Cleanup_Func cleanup_func)
@@ -23,6 +28,10 @@ e_object_alloc(int size, int type, E_Object_Cleanup_Func cleanup_func)
    obj->type = type;
    obj->references = 1;
    obj->cleanup_func = cleanup_func;
+#ifdef OBJECT_HASH_CHECK
+   if (e_obj_hash_check)
+     eina_hash_add(e_obj_hash, &obj, obj);
+#endif
    return obj;
 }
 
@@ -117,6 +126,10 @@ e_object_free(E_Object *obj)
    obj->magic = E_OBJECT_MAGIC_FREED;
 #endif
    obj->cleanup_func(obj);
+#ifdef OBJECT_HASH_CHECK
+   if (e_obj_hash_check)
+     eina_hash_del_by_key(e_obj_hash, &obj);
+#endif
 }
 
 EAPI int
@@ -424,6 +437,29 @@ e_object_delfn_del(E_Object *obj, E_Object_Delfn *dfn)
    }
  */
 
+#ifdef OBJECT_HASH_CHECK
+EAPI void
+e_object_hash_init(void)
+{
+   char *val;
+
+   e_obj_hash_check = EINA_FALSE;
+
+   val = getenv("E_OBJECT_HASH_CHECK");
+   if ((val) && (!strcmp(val, "1")))
+     {
+        e_obj_hash_check = EINA_TRUE;
+        e_obj_hash = eina_hash_pointer_new(NULL);
+     }
+}
+
+EAPI void
+e_object_hash_shutdown(void)
+{
+   E_FREE_FUNC(e_obj_hash, eina_hash_free);
+}
+#endif
+
 #ifdef OBJECT_PARANOIA_CHECK
 /* local subsystem functions */
 static void
index 74bb4b5da38c01d77b7bfe0ed4c930e3e9f02050..0f6eaeed10aafef64e190aa7d23469771bcbf1c0 100644 (file)
 #define E_OBJECT_ALLOC(x, type, cleanup_func) e_object_alloc(sizeof(x), (type), E_OBJECT_CLEANUP_FUNC(cleanup_func))
 #define E_OBJECT_DEL_SET(x, del_func)   e_object_del_func_set(E_OBJECT(x), E_OBJECT_CLEANUP_FUNC(del_func))
 
+#ifdef OBJECT_HASH_CHECK
+# define E_OBJECT_HASH_FIND(x)          e_object_hash_find(E_OBJECT(x))
+#endif
+
 #ifdef OBJECT_PARANOIA_CHECK
 # define E_OBJECT_CHECK(x)                       do {if (e_object_error(E_OBJECT(x))) return;} while (0)
 # define E_OBJECT_CHECK_RETURN(x, ret)           do {if (e_object_error(E_OBJECT(x))) return ret;} while (0)
 #  define E_OBJECT_IF_NOT_TYPE(x, tp)            if (E_OBJECT(x)->type != (tp))
 #else
 # ifdef OBJECT_CHECK
-#  define E_OBJECT_CHECK(x)                       do {if ((!E_OBJECT(x)) || (E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return;} while (0)
-#  define E_OBJECT_CHECK_RETURN(x, ret)           do {if ((!E_OBJECT(x)) || (E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return ret;} while (0)
+#  ifdef OBJECT_HASH_CHECK
+#   define E_OBJECT_CHECK(x)                                              \
+   do {                                                                   \
+     if (!E_OBJECT(x))return;                                             \
+     else if ((e_obj_hash_check) && (!E_OBJECT_HASH_FIND(x))) return;     \
+     else if ((E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return;        \
+   } while (0)
+#   define E_OBJECT_CHECK_RETURN(x, ret)                                  \
+   do {                                                                   \
+     if (!E_OBJECT(x)) return ret;                                        \
+     else if ((e_obj_hash_check) && (!E_OBJECT_HASH_FIND(x))) return ret; \
+     else if ((E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return ret;    \
+   } while (0)
+#  else
+#   define E_OBJECT_CHECK(x)                      do {if ((!E_OBJECT(x)) || (E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return;} while (0)
+#   define E_OBJECT_CHECK_RETURN(x, ret)          do {if ((!E_OBJECT(x)) || (E_OBJECT(x)->magic != (int)E_OBJECT_MAGIC)) return ret;} while (0)
+#  endif
 #  define E_OBJECT_TYPE_CHECK(x, tp)              do {if ((E_OBJECT(x)->type) != (int)(tp)) { CRI("Object type check failed in %s", __FUNCTION__); return;} } while (0)
 #  define E_OBJECT_TYPE_CHECK_RETURN(x, tp, ret)  do {if ((E_OBJECT(x)->type) != (int)(tp)) { CRI("Object type check failed in %s", __FUNCTION__); return ret;} } while (0)
 #  define E_OBJECT_IF_NOT_TYPE(x, tp)             if (E_OBJECT(x)->type != (int)(tp))
@@ -103,6 +122,20 @@ EAPI void            e_object_delfn_clear(E_Object *obj);
 
 EAPI void e_object_ref_debug_set(E_Object *obj, Eina_Bool set);
 
+#ifdef OBJECT_HASH_CHECK
+extern EAPI Eina_Bool e_obj_hash_check;
+extern EAPI Eina_Hash *e_obj_hash;
+
+EAPI void      e_object_hash_init       (void);
+EAPI void      e_object_hash_shutdown   (void);
+
+static inline E_Object *
+e_object_hash_find(E_Object *obj)
+{
+   return (E_Object *)eina_hash_find(e_obj_hash, &obj);
+}
+#endif
+
 /*
 EAPI void  e_object_breadcrumb_add      (E_Object *obj, char *crumb);
 EAPI void  e_object_breadcrumb_del      (E_Object *obj, char *crumb);