* eet: fix bad allocation case triggered by edje new file format.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 13 Aug 2010 15:21:52 +0000 (15:21 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 13 Aug 2010 15:21:52 +0000 (15:21 +0000)
Bad news, I also discovered in the same time that we introduced an
API/ABI breakage in 1.3.0. This patch does prevent it from coming
again, sadly, it imply an ABI break that I didn't find a proper
way to work around. So recompile eet and all the program that use
it after that commit.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eet@51080 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/lib/Eet.h
src/lib/eet_data.c
src/tests/eet_data_suite.c
src/tests/eet_suite.c

index 73ea9a6..ce4ec2f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
        * Add EET_DATA_DESCRIPTOR_ADD_HASH_STRING.
 
+2010-08-06  Cedric BAIL
+
+       * Break eet_eina_* function helper to provide a clean API/ABI to
+       prevent futur break. This should prevent the ABI break that was
+       introduced with release 1.3.0.
+
+       * Add a specific allocator for array. This should fix wrong allocation
+       case discovered with recent edje file format change.
index 8fc5a8b..897ebc0 100644 (file)
@@ -1736,7 +1736,7 @@ typedef struct _Eet_Data_Descriptor         Eet_Data_Descriptor;
  * version member so it is compatible with abi changes, or at least
  * will not crash with them.
  */
-#define EET_DATA_DESCRIPTOR_CLASS_VERSION 3
+#define EET_DATA_DESCRIPTOR_CLASS_VERSION 4
 
 /**
  * @typedef Eet_Data_Descriptor_Class
@@ -1778,6 +1778,8 @@ struct _Eet_Data_Descriptor_Class
       void        (*str_direct_free)(const char *str);   /**< how to free a string returned by str_direct_alloc */
       const char *(*type_get)(const void *data, Eina_Bool *unknow);    /**< convert any kind of data type to a name that define an Eet_Data_Element. */
       Eina_Bool   (*type_set)(const char *type, void *data, Eina_Bool unknow);    /**< set the type at a particular adress */
+      void      * (*array_alloc)(size_t size); /**< how to allocate memory for array (usually malloc()) */
+      void        (*array_free)(void *mem); /**< how to free memory for array (usually malloc()) */
    } func;
 };
 
@@ -1914,6 +1916,7 @@ EAPI Eet_Data_Descriptor *                    eet_data_descriptor_file_new(const
  * @ingroup Eet_Data_Group
  */
 EAPI Eina_Bool                                eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
+                                                                                       unsigned int               eddc_size,
                                                                                         const char                *name,
                                                                                         int                        size);
 
@@ -1931,7 +1934,7 @@ EAPI Eina_Bool                                eet_eina_stream_data_descriptor_cl
  * @ingroup Eet_Data_Group
  */
 #define EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(clas, type)\
-   (eet_eina_stream_data_descriptor_class_set(clas, # type, sizeof(type)))
+   (eet_eina_stream_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type)))
 
 /**
  * This function is an helper that set all the parameter of an
@@ -1948,6 +1951,7 @@ EAPI Eina_Bool                                eet_eina_stream_data_descriptor_cl
  * @ingroup Eet_Data_Group
  */
 EAPI Eina_Bool      eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
+                                                           unsigned int               eddc_size,
                                                             const char                *name,
                                                             int                        size);
 
@@ -1964,8 +1968,8 @@ EAPI Eina_Bool      eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_
  * @since 1.2.3
  * @ingroup Eet_Data_Group
  */
-#define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) (\
-      eet_eina_file_data_descriptor_class_set(clas, # type, sizeof(type)))
+#define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type)\
+  (eet_eina_file_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type)))
 
 /**
  * This function frees a data descriptor when it is not needed anymore.
index 47929e1..17d70fb 100644 (file)
@@ -138,6 +138,8 @@ struct _Eet_Data_Descriptor
       void        (*hash_free)(void *h);
       const char *(*type_get)(const void *data, Eina_Bool *unknow);
       Eina_Bool   (*type_set)(const char *type, void *data, Eina_Bool unknow);
+      void      * (*array_alloc)(size_t size);
+      void        (*array_free)(void *mem);
    } func;
    struct
    {
@@ -186,6 +188,7 @@ struct _Eet_Free
 struct _Eet_Free_Context
 {
    Eet_Free freelist;
+   Eet_Free freelist_array;
    Eet_Free freelist_list;
    Eet_Free freelist_hash;
    Eet_Free freelist_str;
@@ -1670,10 +1673,12 @@ _eet_eina_hash_free(void *hash)
 /*---*/
 EAPI Eina_Bool
 eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
+                                         /* When we change the structure content in the future, we need to handle old structure type too */
+                                         unsigned int               eddc_size,
                                           const char                *name,
                                           int                        size)
 {
-   if (!eddc || !name)
+   if (!eddc || !name || eddc_size != sizeof (Eet_Data_Descriptor_Class))
       return EINA_FALSE;
 
    eddc->name = name;
@@ -1692,15 +1697,21 @@ eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
    eddc->func.hash_add = (void * (*)(void *, const char *, void *))_eet_eina_hash_add_alloc;
    eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free;
 
+   /* This will cause an ABI incompatibility */
+   eddc->func.array_alloc = _eet_mem_alloc;
+   eddc->func.array_free = _eet_mem_free;
+
    return EINA_TRUE;
 } /* eet_eina_stream_data_descriptor_class_set */
 
 EAPI Eina_Bool
 eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
+                                       /* When we change the structure content in the future, we need to handle old structure type too */
+                                       unsigned int               eddc_size,
                                         const char                *name,
                                         int                        size)
 {
-   if (!eet_eina_stream_data_descriptor_class_set(eddc, name, size))
+   if (!eet_eina_stream_data_descriptor_class_set(eddc, eddc_size, name, size))
       return EINA_FALSE;
 
    eddc->version = 2;
@@ -1764,6 +1775,12 @@ _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc,
         edd->func.type_set = eddc->func.type_set;
      }
 
+   if (eddc->version > 3)
+     {
+       edd->func.array_alloc = eddc->func.array_alloc;
+       edd->func.array_free = eddc->func.array_free;
+     }
+
    return edd;
 } /* _eet_data_descriptor_new */
 
@@ -2154,6 +2171,37 @@ _eet_freelist_free(Eet_Free_Context    *context,
    _eet_free_reset(&context->freelist);
 } /* _eet_freelist_free */
 
+#define _eet_freelist_array_add(Ctx, Data) _eet_free_add(&Ctx->freelist_array, Data);
+#define _eet_freelist_array_reset(Ctx)     _eet_free_reset(&Ctx->freelist_array);
+#define _eet_freelist_array_ref(Ctx)       _eet_free_ref(&Ctx->freelist_array);
+#define _eet_freelist_array_unref(Ctx)     _eet_free_unref(&Ctx->freelist_array);
+
+static void
+_eet_freelist_array_free(Eet_Free_Context    *context,
+                        Eet_Data_Descriptor *edd)
+{
+   int j;
+   int i;
+
+   if (context->freelist_array.ref > 0)
+      return;
+
+   for (j = 0; j < 256; ++j)
+      for (i = 0; i < context->freelist_array.num[j]; ++i)
+        {
+           if (edd)
+            {
+               if (edd->func.array_free)
+                 edd->func.array_free(context->freelist_array.list[j][i]);
+               else
+                 edd->func.mem_free(context->freelist_array.list[j][i]);
+            }
+           else
+              free(context->freelist_array.list[j][i]);
+        }
+   _eet_free_reset(&context->freelist_array);
+} /* _eet_freelist_array_free */
+
 #define _eet_freelist_list_add(Ctx, Data) _eet_free_add(&Ctx->freelist_list, Data);
 #define _eet_freelist_list_reset(Ctx)     _eet_free_reset(&Ctx->freelist_list);
 #define _eet_freelist_list_ref(Ctx)       _eet_free_ref(&Ctx->freelist_list);
@@ -3224,6 +3272,7 @@ _eet_data_descriptor_decode(Eet_Free_Context     *context,
         _eet_freelist_direct_str_free(context, edd);
         _eet_freelist_list_free(context, edd);
         _eet_freelist_hash_free(context, edd);
+       _eet_freelist_array_free(context, edd);
         _eet_freelist_free(context, edd);
      }
    else
@@ -3233,6 +3282,7 @@ _eet_data_descriptor_decode(Eet_Free_Context     *context,
         _eet_freelist_list_reset(context);
         _eet_freelist_hash_reset(context);
         _eet_freelist_direct_str_reset(context);
+       _eet_freelist_array_reset(context);
      }
 
    if (!edd)
@@ -3248,6 +3298,7 @@ error:
    _eet_freelist_direct_str_free(context, edd);
    _eet_freelist_list_free(context, edd);
    _eet_freelist_hash_free(context, edd);
+   _eet_freelist_array_free(context, edd);
    _eet_freelist_free(context, edd);
 
    /* FIXME: Warn that something goes wrong here. */
@@ -3454,14 +3505,17 @@ eet_data_get_array(Eet_Free_Context     *context,
               * on the counter offset */
              *(int *)(((char *)data) + ede->count - ede->offset) = count;
              /* allocate space for the array of elements */
-             *(void **)ptr = edd->func.mem_alloc(count * subsize);
+            if (edd->func.array_alloc)
+              *(void **) ptr = edd->func.array_alloc(count * subsize);
+            else
+              *(void **) ptr = edd->func.mem_alloc(count * subsize);
 
              if (!*(void **)ptr)
                 return 0;
 
              memset(*(void **)ptr, 0, count * subsize);
 
-             _eet_freelist_add(context, *(void **)ptr);
+             _eet_freelist_array_add(context, *(void **)ptr);
           }
      }
 
index 5ec7e01..f6fb7f1 100644 (file)
@@ -63,5 +63,7 @@ eet_test_setup_eddc(Eet_Data_Descriptor_Class * eddc)
    eddc->func.hash_free = (void *)_eet_eina_hash_free;
    eddc->func.str_direct_alloc = (void *)_eet_str_direct_alloc;
    eddc->func.str_direct_free = (void *)_eet_str_direct_free;
+   eddc->func.array_alloc = NULL;
+   eddc->func.array_free = NULL;
 } /* eet_test_setup_eddc */
 
index ce36fac..9c4d5f0 100644 (file)
@@ -1121,7 +1121,8 @@ START_TEST(eet_file_data_dump_test)
    memset(&etbt.charray, 0, sizeof(etbt.charray));
    etbt.charray[0] = "test";
 
-   eet_eina_file_data_descriptor_class_set(&eddc, "Eet_Test_Ex_Type",
+   eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc),
+                                          "Eet_Test_Ex_Type",
                                            sizeof(Eet_Test_Ex_Type));
 
    edd = eet_data_descriptor_file_new(&eddc);
@@ -2041,7 +2042,8 @@ START_TEST(eet_connection_check)
    memset(&etbt.charray, 0, sizeof(etbt.charray));
    etbt.charray[0] = "test";
 
-   eet_eina_file_data_descriptor_class_set(&eddc, "Eet_Test_Ex_Type",
+   eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc),
+                                          "Eet_Test_Ex_Type",
                                            sizeof(Eet_Test_Ex_Type));
 
    edd = eet_data_descriptor_file_new(&eddc);
@@ -2113,7 +2115,7 @@ START_TEST(eet_fp)
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1",   f1,   EET_T_F32P32);
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0",   f0,   EET_T_F32P32);
 
-   eet_eina_stream_data_descriptor_class_set(&eddc, "Eet_5FP", sizeof (Eet_5DBL));
+   eet_eina_stream_data_descriptor_class_set(&eddc, sizeof (eddc), "Eet_5FP", sizeof (Eet_5DBL));
    edd_5DBL = eet_data_descriptor_stream_new(&eddc);
 
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE);
@@ -2175,7 +2177,7 @@ START_TEST(eet_file_fp)
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1",   f1,   EET_T_F32P32);
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0",   f0,   EET_T_F32P32);
 
-   eet_eina_file_data_descriptor_class_set(&eddc, "Eet_5FP", sizeof (Eet_5DBL));
+   eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc), "Eet_5FP", sizeof (Eet_5DBL));
    edd_5DBL = eet_data_descriptor_file_new(&eddc);
 
    EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE);