From f54245420a08b452b2451ae9f955e4eef299b41a Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Mon, 7 Jul 2003 07:52:20 +0000 Subject: [PATCH] make sure eet doesn't leak on "bad decoding". this means api changes though - sorry. SVN revision: 7112 --- legacy/eet/src/bin/eet_main.c | 18 +++-- legacy/eet/src/lib/Eet.h | 14 ++-- legacy/eet/src/lib/eet_data.c | 128 +++++++++++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 18 deletions(-) diff --git a/legacy/eet/src/bin/eet_main.c b/legacy/eet/src/bin/eet_main.c index 0bf1a717cb..c8690f6b73 100644 --- a/legacy/eet/src/bin/eet_main.c +++ b/legacy/eet/src/bin/eet_main.c @@ -56,24 +56,30 @@ encdectest(void) evas_list_next, evas_list_append, evas_list_data, - evas_hash_foreach, - evas_hash_add); + evas_list_free, + evas_hash_foreach, + evas_hash_add, + evas_hash_free); EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING); edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2), evas_list_next, evas_list_append, evas_list_data, - evas_hash_foreach, - evas_hash_add); + evas_list_free, + evas_hash_foreach, + evas_hash_add, + evas_hash_free); EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING); edd = eet_data_descriptor_new("blah", sizeof(Blah), evas_list_next, evas_list_append, evas_list_data, - evas_hash_foreach, - evas_hash_add); + evas_list_free, + 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, "sixteen", sixteen, EET_T_SHORT); EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT); diff --git a/legacy/eet/src/lib/Eet.h b/legacy/eet/src/lib/Eet.h index 91d0fea0b9..faad258ad2 100644 --- a/legacy/eet/src/lib/Eet.h +++ b/legacy/eet/src/lib/Eet.h @@ -394,24 +394,30 @@ extern "C" { * evas_list_next, * evas_list_append, * evas_list_data, + * evas_list_free, * evas_hash_foreach, - * evas_hash_add); + * evas_hash_add, + * evas_hash_free); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING); * * edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2), * evas_list_next, * evas_list_append, * evas_list_data, + * evas_list_free, * evas_hash_foreach, - * evas_hash_add); + * evas_hash_add, + * evas_hash_free); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING); * * edd = eet_data_descriptor_new("blah", sizeof(Blah), * evas_list_next, * evas_list_append, * evas_list_data, + * evas_list_free, * 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, "sixteen", sixteen, EET_T_SHORT); * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT); @@ -484,7 +490,7 @@ extern "C" { * @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. diff --git a/legacy/eet/src/lib/eet_data.c b/legacy/eet/src/lib/eet_data.c index 0b44d5abce..51b02f3199 100644 --- a/legacy/eet/src/lib/eet_data.c +++ b/legacy/eet/src/lib/eet_data.c @@ -78,8 +78,10 @@ struct _Eet_Data_Descriptor void *(*list_next) (void *l); void *(*list_append) (void *l, void *d); 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_add) (void *h, const char *k, void *d); + void (*hash_free) (void *h); } func; struct { int num; @@ -1274,7 +1276,7 @@ eet_data_image_read(Eet_File *ef, char *name, int size; unsigned int *d = NULL; int header[8]; - + data = eet_read(ef, name, &size); if (!data) return NULL; 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_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_add) (void *h, const char *k, void *d), + void (*func_hash_free) (void *h)) { Eet_Data_Descriptor *edd; @@ -1440,8 +1444,10 @@ eet_data_descriptor_new(char *name, edd->func.list_next = func_list_next; edd->func.list_append = func_list_append; edd->func.list_data = func_list_data; + edd->func.list_free = func_list_free; edd->func.hash_foreach = func_hash_foreach; edd->func.hash_add = func_hash_add; + edd->func.hash_free = func_hash_free; return edd; } @@ -1512,6 +1518,82 @@ eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, i 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 * eet_data_descriptor_decode(Eet_Data_Descriptor *edd, void *data_in, @@ -1533,16 +1615,19 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, data = calloc(1, edd->size); if (!data) return NULL; + _eet_freelist_add(data); chnk = eet_data_chunk_get(data_in, size_in); if (!chnk) { - free(data); + _eet_freelist_free(); + _eet_freelist_list_free(edd); return NULL; } if (strcmp(chnk->name, edd->name)) { eet_data_chunk_free(chnk); - free(data); + _eet_freelist_free(); + _eet_freelist_list_free(edd); return NULL; } p = chnk->data; @@ -1556,8 +1641,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, echnk = eet_data_chunk_get(p, size); if (!echnk) { - /* FIXME: partially built data struct - leak!!!! */ - free(data); + _eet_freelist_free(); + _eet_freelist_list_free(edd); eet_data_chunk_free(chnk); return NULL; } @@ -1588,6 +1673,13 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, data_ret = eet_data_descriptor_decode(ede->subtype, echnk->data, 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 *)data_ret; } @@ -1618,16 +1710,26 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, data_ret = calloc(1, eet_coder[ede->type].size); if (data_ret) { + _eet_freelist_add(data_ret); ret = eet_data_get_type(ede->type, echnk->data, ((char *)echnk->data) + echnk->size, data_ret); if (ret <= 0) { - free(data_ret); - data_ret = NULL; + _eet_freelist_free(); + _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) { @@ -1639,6 +1741,14 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, { list = edd->func.list_append(list, data_ret); *ptr = list; + _eet_freelist_list_add(ptr); + } + else + { + _eet_freelist_free(); + _eet_freelist_list_free(edd); + eet_data_chunk_free(chnk); + return NULL; } } break; @@ -1658,6 +1768,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd, eet_data_chunk_free(echnk); } eet_data_chunk_free(chnk); + _eet_freelist_reset(); + _eet_freelist_list_reset(); return data; }