make sure eet doesn't leak on "bad decoding". this means api changes though -

sorry.


SVN revision: 7112
This commit is contained in:
Carsten Haitzler 2003-07-07 07:52:20 +00:00
parent 1bf1f933a9
commit f54245420a
3 changed files with 142 additions and 18 deletions

View File

@ -56,24 +56,30 @@ encdectest(void)
evas_list_next, evas_list_next,
evas_list_append, evas_list_append,
evas_list_data, evas_list_data,
evas_hash_foreach, evas_list_free,
evas_hash_add); evas_hash_foreach,
evas_hash_add,
evas_hash_free);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING);
edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2), edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2),
evas_list_next, evas_list_next,
evas_list_append, evas_list_append,
evas_list_data, evas_list_data,
evas_hash_foreach, evas_list_free,
evas_hash_add); evas_hash_foreach,
evas_hash_add,
evas_hash_free);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING);
edd = eet_data_descriptor_new("blah", sizeof(Blah), edd = eet_data_descriptor_new("blah", sizeof(Blah),
evas_list_next, evas_list_next,
evas_list_append, evas_list_append,
evas_list_data, evas_list_data,
evas_hash_foreach, evas_list_free,
evas_hash_add); evas_hash_foreach,
evas_hash_add,
evas_hash_free);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "character", character, EET_T_CHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "character", character, EET_T_CHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "sixteen", sixteen, EET_T_SHORT); EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "sixteen", sixteen, EET_T_SHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT);

View File

@ -394,24 +394,30 @@ extern "C" {
* evas_list_next, * evas_list_next,
* evas_list_append, * evas_list_append,
* evas_list_data, * evas_list_data,
* evas_list_free,
* evas_hash_foreach, * evas_hash_foreach,
* evas_hash_add); * evas_hash_add,
* evas_hash_free);
* EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING);
* *
* edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2), * edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2),
* evas_list_next, * evas_list_next,
* evas_list_append, * evas_list_append,
* evas_list_data, * evas_list_data,
* evas_list_free,
* evas_hash_foreach, * evas_hash_foreach,
* evas_hash_add); * evas_hash_add,
* evas_hash_free);
* EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING);
* *
* edd = eet_data_descriptor_new("blah", sizeof(Blah), * edd = eet_data_descriptor_new("blah", sizeof(Blah),
* evas_list_next, * evas_list_next,
* evas_list_append, * evas_list_append,
* evas_list_data, * evas_list_data,
* evas_list_free,
* evas_hash_foreach, * evas_hash_foreach,
* evas_hash_add); * evas_hash_add,
* evas_hash_free);
* EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "character", character, EET_T_CHAR); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "character", character, EET_T_CHAR);
* EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "sixteen", sixteen, EET_T_SHORT); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "sixteen", sixteen, EET_T_SHORT);
* EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT);
@ -484,7 +490,7 @@ extern "C" {
* @endcode * @endcode
* *
*/ */
Eet_Data_Descriptor *eet_data_descriptor_new(char *name, int size, void *(*func_list_next) (void *l), void *(*func_list_append) (void *l, void *d), void *(*func_list_data) (void *l), void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt), void *(*func_hash_add) (void *h, const char *k, void *d)); Eet_Data_Descriptor *eet_data_descriptor_new(char *name, int size, void *(*func_list_next) (void *l), void *(*func_list_append) (void *l, void *d), void *(*func_list_data) (void *l), void *(*func_list_free) (void *l), void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt), void *(*func_hash_add) (void *h, const char *k, void *d), void (*func_hash_free) (void *h));
/** /**
* 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

@ -78,8 +78,10 @@ struct _Eet_Data_Descriptor
void *(*list_next) (void *l); void *(*list_next) (void *l);
void *(*list_append) (void *l, void *d); void *(*list_append) (void *l, void *d);
void *(*list_data) (void *l); void *(*list_data) (void *l);
void *(*list_free) (void *l);
void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt); void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
void *(*hash_add) (void *h, const char *k, void *d); void *(*hash_add) (void *h, const char *k, void *d);
void (*hash_free) (void *h);
} func; } func;
struct { struct {
int num; int num;
@ -1274,7 +1276,7 @@ eet_data_image_read(Eet_File *ef, char *name,
int size; int size;
unsigned int *d = NULL; unsigned int *d = NULL;
int header[8]; int header[8];
data = eet_read(ef, name, &size); data = eet_read(ef, name, &size);
if (!data) return NULL; if (!data) return NULL;
d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy); d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy);
@ -1428,8 +1430,10 @@ eet_data_descriptor_new(char *name,
void *(*func_list_next) (void *l), void *(*func_list_next) (void *l),
void *(*func_list_append) (void *l, void *d), void *(*func_list_append) (void *l, void *d),
void *(*func_list_data) (void *l), void *(*func_list_data) (void *l),
void *(*func_list_free) (void *l),
void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt), void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt),
void *(*func_hash_add) (void *h, const char *k, void *d)) void *(*func_hash_add) (void *h, const char *k, void *d),
void (*func_hash_free) (void *h))
{ {
Eet_Data_Descriptor *edd; Eet_Data_Descriptor *edd;
@ -1440,8 +1444,10 @@ eet_data_descriptor_new(char *name,
edd->func.list_next = func_list_next; edd->func.list_next = func_list_next;
edd->func.list_append = func_list_append; edd->func.list_append = func_list_append;
edd->func.list_data = func_list_data; edd->func.list_data = func_list_data;
edd->func.list_free = func_list_free;
edd->func.hash_foreach = func_hash_foreach; edd->func.hash_foreach = func_hash_foreach;
edd->func.hash_add = func_hash_add; edd->func.hash_add = func_hash_add;
edd->func.hash_free = func_hash_free;
return edd; return edd;
} }
@ -1512,6 +1518,82 @@ eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, i
return val; return val;
} }
static int freelist_len = 0;
static int freelist_num = 0;
static void **freelist = NULL;
static void
_eet_freelist_add(void *data)
{
freelist_num++;
if (freelist_num > freelist_len)
{
freelist_len += 16;
freelist = realloc(freelist, freelist_len * sizeof(void *));
}
freelist[freelist_num - 1] = data;
}
static void
_eet_freelist_reset(void)
{
freelist_len = 0;
freelist_num = 0;
if (freelist) free(freelist);
freelist = NULL;
}
static void
_eet_freelist_free(void)
{
int i;
for (i = 0; i < freelist_num; i++)
free(freelist[i]);
_eet_freelist_reset();
}
static int freelist_list_len = 0;
static int freelist_list_num = 0;
static void ***freelist_list = NULL;
static void
_eet_freelist_list_add(void **data)
{
int i;
for (i = 0; i < freelist_list_num; i++)
{
if (freelist_list[i] == data) return;
}
freelist_list_num++;
if (freelist_list_num > freelist_list_len)
{
freelist_list_len += 16;
freelist_list = realloc(freelist_list, freelist_list_len * sizeof(void *));
}
freelist_list[freelist_list_num - 1] = data;
}
static void
_eet_freelist_list_reset(void)
{
freelist_list_len = 0;
freelist_list_num = 0;
if (freelist_list) free(freelist_list);
freelist_list = NULL;
}
static void
_eet_freelist_list_free(Eet_Data_Descriptor *edd)
{
int i;
for (i = 0; i < freelist_list_num; i++)
edd->func.list_free(*(freelist_list[i]));
_eet_freelist_list_reset();
}
void * void *
eet_data_descriptor_decode(Eet_Data_Descriptor *edd, eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
void *data_in, void *data_in,
@ -1533,16 +1615,19 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
data = calloc(1, edd->size); data = calloc(1, edd->size);
if (!data) return NULL; if (!data) return NULL;
_eet_freelist_add(data);
chnk = eet_data_chunk_get(data_in, size_in); chnk = eet_data_chunk_get(data_in, size_in);
if (!chnk) if (!chnk)
{ {
free(data); _eet_freelist_free();
_eet_freelist_list_free(edd);
return NULL; return NULL;
} }
if (strcmp(chnk->name, edd->name)) if (strcmp(chnk->name, edd->name))
{ {
eet_data_chunk_free(chnk); eet_data_chunk_free(chnk);
free(data); _eet_freelist_free();
_eet_freelist_list_free(edd);
return NULL; return NULL;
} }
p = chnk->data; p = chnk->data;
@ -1556,8 +1641,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
echnk = eet_data_chunk_get(p, size); echnk = eet_data_chunk_get(p, size);
if (!echnk) if (!echnk)
{ {
/* FIXME: partially built data struct - leak!!!! */ _eet_freelist_free();
free(data); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); eet_data_chunk_free(chnk);
return NULL; return NULL;
} }
@ -1588,6 +1673,13 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
data_ret = eet_data_descriptor_decode(ede->subtype, data_ret = eet_data_descriptor_decode(ede->subtype,
echnk->data, echnk->data,
echnk->size); echnk->size);
if (!data_ret)
{
_eet_freelist_free();
_eet_freelist_list_free(edd);
eet_data_chunk_free(chnk);
return NULL;
}
ptr = (void **)(((char *)data) + ede->offset); ptr = (void **)(((char *)data) + ede->offset);
*ptr = (void *)data_ret; *ptr = (void *)data_ret;
} }
@ -1618,16 +1710,26 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
data_ret = calloc(1, eet_coder[ede->type].size); data_ret = calloc(1, eet_coder[ede->type].size);
if (data_ret) if (data_ret)
{ {
_eet_freelist_add(data_ret);
ret = eet_data_get_type(ede->type, ret = eet_data_get_type(ede->type,
echnk->data, echnk->data,
((char *)echnk->data) + echnk->size, ((char *)echnk->data) + echnk->size,
data_ret); data_ret);
if (ret <= 0) if (ret <= 0)
{ {
free(data_ret); _eet_freelist_free();
data_ret = NULL; _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk);
return NULL;
} }
} }
else
{
_eet_freelist_free();
_eet_freelist_list_free(edd);
eet_data_chunk_free(chnk);
return NULL;
}
} }
else if (ede->subtype) else if (ede->subtype)
{ {
@ -1639,6 +1741,14 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
{ {
list = edd->func.list_append(list, data_ret); list = edd->func.list_append(list, data_ret);
*ptr = list; *ptr = list;
_eet_freelist_list_add(ptr);
}
else
{
_eet_freelist_free();
_eet_freelist_list_free(edd);
eet_data_chunk_free(chnk);
return NULL;
} }
} }
break; break;
@ -1658,6 +1768,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
eet_data_chunk_free(echnk); eet_data_chunk_free(echnk);
} }
eet_data_chunk_free(chnk); eet_data_chunk_free(chnk);
_eet_freelist_reset();
_eet_freelist_list_reset();
return data; return data;
} }