From d0f668a6ba6818e2c57c486661f7a3a9b848ddaa Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 13 Aug 2010 15:21:52 +0000 Subject: [PATCH] * eet: fix bad allocation case triggered by edje new file format. 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. SVN revision: 51080 --- legacy/eet/ChangeLog | 8 ++++ legacy/eet/src/lib/Eet.h | 12 ++++-- legacy/eet/src/lib/eet_data.c | 62 +++++++++++++++++++++++++-- legacy/eet/src/tests/eet_data_suite.c | 2 + legacy/eet/src/tests/eet_suite.c | 10 +++-- 5 files changed, 82 insertions(+), 12 deletions(-) diff --git a/legacy/eet/ChangeLog b/legacy/eet/ChangeLog index 73ea9a65f1..ce4ec2fcc3 100644 --- a/legacy/eet/ChangeLog +++ b/legacy/eet/ChangeLog @@ -418,3 +418,11 @@ * 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. diff --git a/legacy/eet/src/lib/Eet.h b/legacy/eet/src/lib/Eet.h index 8fc5a8b83b..897ebc0874 100644 --- a/legacy/eet/src/lib/Eet.h +++ b/legacy/eet/src/lib/Eet.h @@ -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. diff --git a/legacy/eet/src/lib/eet_data.c b/legacy/eet/src/lib/eet_data.c index 47929e188e..17d70fb5e6 100644 --- a/legacy/eet/src/lib/eet_data.c +++ b/legacy/eet/src/lib/eet_data.c @@ -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); } } diff --git a/legacy/eet/src/tests/eet_data_suite.c b/legacy/eet/src/tests/eet_data_suite.c index 5ec7e013a6..f6fb7f1100 100644 --- a/legacy/eet/src/tests/eet_data_suite.c +++ b/legacy/eet/src/tests/eet_data_suite.c @@ -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 */ diff --git a/legacy/eet/src/tests/eet_suite.c b/legacy/eet/src/tests/eet_suite.c index ce36fac84a..9c4d5f0a1c 100644 --- a/legacy/eet/src/tests/eet_suite.c +++ b/legacy/eet/src/tests/eet_suite.c @@ -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);