make sure eet doesn't leak on "bad decoding". this means api changes though -
authorraster <raster>
Mon, 7 Jul 2003 07:52:20 +0000 (07:52 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 7 Jul 2003 07:52:20 +0000 (07:52 +0000)
sorry.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/libs/eet@7112 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/eet_main.c
src/lib/Eet.h
src/lib/eet_data.c

index 0bf1a71..c8690f6 100644 (file)
@@ -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);
index 91d0fea..faad258 100644 (file)
@@ -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.
index 0b44d5a..51b02f3 100644 (file)
@@ -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;
 }