* 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
This commit is contained in:
Cedric BAIL 2010-08-13 15:21:52 +00:00
parent 02031b60bf
commit d0f668a6ba
5 changed files with 82 additions and 12 deletions

View File

@ -418,3 +418,11 @@
* Add EET_DATA_DESCRIPTOR_ADD_HASH_STRING. * 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.

View 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 * version member so it is compatible with abi changes, or at least
* will not crash with them. * will not crash with them.
*/ */
#define EET_DATA_DESCRIPTOR_CLASS_VERSION 3 #define EET_DATA_DESCRIPTOR_CLASS_VERSION 4
/** /**
* @typedef Eet_Data_Descriptor_Class * @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 */ 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. */ 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 */ 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; } func;
}; };
@ -1914,6 +1916,7 @@ EAPI Eet_Data_Descriptor * eet_data_descriptor_file_new(const
* @ingroup Eet_Data_Group * @ingroup Eet_Data_Group
*/ */
EAPI Eina_Bool eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, EAPI Eina_Bool eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
unsigned int eddc_size,
const char *name, const char *name,
int size); int size);
@ -1931,7 +1934,7 @@ EAPI Eina_Bool eet_eina_stream_data_descriptor_cl
* @ingroup Eet_Data_Group * @ingroup Eet_Data_Group
*/ */
#define EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(clas, type)\ #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 * 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 * @ingroup Eet_Data_Group
*/ */
EAPI Eina_Bool eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, EAPI Eina_Bool eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
unsigned int eddc_size,
const char *name, const char *name,
int size); int size);
@ -1964,8 +1968,8 @@ EAPI Eina_Bool eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_
* @since 1.2.3 * @since 1.2.3
* @ingroup Eet_Data_Group * @ingroup Eet_Data_Group
*/ */
#define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) (\ #define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type)\
eet_eina_file_data_descriptor_class_set(clas, # type, sizeof(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. * This function frees a data descriptor when it is not needed anymore.

View File

@ -138,6 +138,8 @@ struct _Eet_Data_Descriptor
void (*hash_free)(void *h); void (*hash_free)(void *h);
const char *(*type_get)(const void *data, Eina_Bool *unknow); const char *(*type_get)(const void *data, Eina_Bool *unknow);
Eina_Bool (*type_set)(const char *type, 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; } func;
struct struct
{ {
@ -186,6 +188,7 @@ struct _Eet_Free
struct _Eet_Free_Context struct _Eet_Free_Context
{ {
Eet_Free freelist; Eet_Free freelist;
Eet_Free freelist_array;
Eet_Free freelist_list; Eet_Free freelist_list;
Eet_Free freelist_hash; Eet_Free freelist_hash;
Eet_Free freelist_str; Eet_Free freelist_str;
@ -1670,10 +1673,12 @@ _eet_eina_hash_free(void *hash)
/*---*/ /*---*/
EAPI Eina_Bool EAPI Eina_Bool
eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, 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, const char *name,
int size) int size)
{ {
if (!eddc || !name) if (!eddc || !name || eddc_size != sizeof (Eet_Data_Descriptor_Class))
return EINA_FALSE; return EINA_FALSE;
eddc->name = name; 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_add = (void * (*)(void *, const char *, void *))_eet_eina_hash_add_alloc;
eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free; 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; return EINA_TRUE;
} /* eet_eina_stream_data_descriptor_class_set */ } /* eet_eina_stream_data_descriptor_class_set */
EAPI Eina_Bool EAPI Eina_Bool
eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, 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, const char *name,
int size) 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; return EINA_FALSE;
eddc->version = 2; 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; 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; return edd;
} /* _eet_data_descriptor_new */ } /* _eet_data_descriptor_new */
@ -2154,6 +2171,37 @@ _eet_freelist_free(Eet_Free_Context *context,
_eet_free_reset(&context->freelist); _eet_free_reset(&context->freelist);
} /* _eet_freelist_free */ } /* _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_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_reset(Ctx) _eet_free_reset(&Ctx->freelist_list);
#define _eet_freelist_list_ref(Ctx) _eet_free_ref(&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_direct_str_free(context, edd);
_eet_freelist_list_free(context, edd); _eet_freelist_list_free(context, edd);
_eet_freelist_hash_free(context, edd); _eet_freelist_hash_free(context, edd);
_eet_freelist_array_free(context, edd);
_eet_freelist_free(context, edd); _eet_freelist_free(context, edd);
} }
else else
@ -3233,6 +3282,7 @@ _eet_data_descriptor_decode(Eet_Free_Context *context,
_eet_freelist_list_reset(context); _eet_freelist_list_reset(context);
_eet_freelist_hash_reset(context); _eet_freelist_hash_reset(context);
_eet_freelist_direct_str_reset(context); _eet_freelist_direct_str_reset(context);
_eet_freelist_array_reset(context);
} }
if (!edd) if (!edd)
@ -3248,6 +3298,7 @@ error:
_eet_freelist_direct_str_free(context, edd); _eet_freelist_direct_str_free(context, edd);
_eet_freelist_list_free(context, edd); _eet_freelist_list_free(context, edd);
_eet_freelist_hash_free(context, edd); _eet_freelist_hash_free(context, edd);
_eet_freelist_array_free(context, edd);
_eet_freelist_free(context, edd); _eet_freelist_free(context, edd);
/* FIXME: Warn that something goes wrong here. */ /* FIXME: Warn that something goes wrong here. */
@ -3454,14 +3505,17 @@ eet_data_get_array(Eet_Free_Context *context,
* on the counter offset */ * on the counter offset */
*(int *)(((char *)data) + ede->count - ede->offset) = count; *(int *)(((char *)data) + ede->count - ede->offset) = count;
/* allocate space for the array of elements */ /* 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) if (!*(void **)ptr)
return 0; return 0;
memset(*(void **)ptr, 0, count * subsize); memset(*(void **)ptr, 0, count * subsize);
_eet_freelist_add(context, *(void **)ptr); _eet_freelist_array_add(context, *(void **)ptr);
} }
} }

View 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.hash_free = (void *)_eet_eina_hash_free;
eddc->func.str_direct_alloc = (void *)_eet_str_direct_alloc; eddc->func.str_direct_alloc = (void *)_eet_str_direct_alloc;
eddc->func.str_direct_free = (void *)_eet_str_direct_free; eddc->func.str_direct_free = (void *)_eet_str_direct_free;
eddc->func.array_alloc = NULL;
eddc->func.array_free = NULL;
} /* eet_test_setup_eddc */ } /* eet_test_setup_eddc */

View File

@ -1121,7 +1121,8 @@ START_TEST(eet_file_data_dump_test)
memset(&etbt.charray, 0, sizeof(etbt.charray)); memset(&etbt.charray, 0, sizeof(etbt.charray));
etbt.charray[0] = "test"; 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)); sizeof(Eet_Test_Ex_Type));
edd = eet_data_descriptor_file_new(&eddc); edd = eet_data_descriptor_file_new(&eddc);
@ -2041,7 +2042,8 @@ START_TEST(eet_connection_check)
memset(&etbt.charray, 0, sizeof(etbt.charray)); memset(&etbt.charray, 0, sizeof(etbt.charray));
etbt.charray[0] = "test"; 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)); sizeof(Eet_Test_Ex_Type));
edd = eet_data_descriptor_file_new(&eddc); 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, "f1", f1, EET_T_F32P32);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, 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); edd_5DBL = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE); 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, "f1", f1, EET_T_F32P32);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, 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); edd_5DBL = eet_data_descriptor_file_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE); EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE);