value: be safer on reset of existing values.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 10 Feb 2012 22:03:48 +0000 (22:03 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 10 Feb 2012 22:03:48 +0000 (22:03 +0000)
if user get and then set the same value, we should not crash and this
may happen with previous code as the old
string/array/value/list... were released, then you ended with the
released memory still being pointed.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@67841 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/eina_inline_value.x
src/lib/eina_value.c

index 6f43c45..2d5f336 100644 (file)
@@ -424,17 +424,22 @@ eina_value_vset(Eina_Value *value, va_list args)
    else if (type == EINA_VALUE_TYPE_STRING)
      {
         const char *str = (const char *) va_arg(args, const char *);
-        free(value->value.ptr);
+        if (value->value.ptr == str) return EINA_TRUE;
         if (!str)
-          value->value.ptr = NULL;
+          {
+             free(value->value.ptr);
+             value->value.ptr = NULL;
+          }
         else
           {
-             value->value.ptr = strdup(str);
-             if (!value->value.ptr)
+             char *tmp = strdup(str);
+             if (!tmp)
                {
                   eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
                   return EINA_FALSE;
                }
+             free(value->value.ptr);
+             value->value.ptr = tmp;
           }
         return EINA_TRUE;
      }
@@ -494,18 +499,22 @@ eina_value_pset(Eina_Value *value, const void *ptr)
           {
              const char * const * pstr = (const char * const *) ptr;
              const char *str = *pstr;
-
-             free(value->value.ptr);
+             if (value->value.ptr == str) return EINA_TRUE;
              if (!str)
-               value->value.ptr = NULL;
+               {
+                  free(value->value.ptr);
+                  value->value.ptr = NULL;
+               }
              else
                {
-                  value->value.ptr = strdup(str);
-                  if (!value->value.ptr)
+                  char *tmp = strdup(str);
+                  if (!tmp)
                     {
                        eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
                        return EINA_FALSE;
                     }
+                  free(value->value.ptr);
+                  value->value.ptr = tmp;
                }
              return EINA_TRUE;
           }
index a4c6428..512591b 100644 (file)
@@ -2317,19 +2317,24 @@ _eina_value_type_string_vset(const Eina_Value_Type *type __UNUSED__, void *mem,
 {
    char **tmem = mem;
    const char *str = va_arg(args, const char *);
-   free(*tmem);
-   if (str == NULL)
-     *tmem = NULL;
+   eina_error_set(0);
+   if (str == *tmem) return EINA_TRUE;
+   if (!str)
+     {
+        free(*tmem);
+        *tmem = NULL;
+     }
    else
      {
-        *tmem = strdup(str);
-        if (*tmem == NULL)
+        char *tmp = strdup(str);
+        if (!tmp)
           {
              eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
              return EINA_FALSE;
           }
+        free(*tmem);
+        *tmem = tmp;
      }
-   eina_error_set(0);
    return EINA_TRUE;
 }
 
@@ -2338,19 +2343,24 @@ _eina_value_type_string_pset(const Eina_Value_Type *type __UNUSED__, void *mem,
 {
    char **tmem = mem;
    const char * const *str = ptr;
-   free(*tmem);
-   if (*str == NULL)
-     *tmem = NULL;
+   eina_error_set(0);
+   if (*str == *tmem) return EINA_TRUE;
+   if (!*str)
+     {
+        free(*tmem);
+        *tmem = NULL;
+     }
    else
      {
-        *tmem = strdup(*str);
-        if (*tmem == NULL)
+        char *tmp = strdup(*str);
+        if (!tmp)
           {
              eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
              return EINA_FALSE;
           }
+        free(*tmem);
+        *tmem = tmp;
      }
-   eina_error_set(0);
    return EINA_TRUE;
 }
 
@@ -2622,6 +2632,7 @@ _eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, c
    const Eina_Value_Array *desc = ptr;
    Eina_Inarray *desc_array;
 
+   eina_error_set(0);
    if ((!tmem->subtype) && (!desc->subtype))
      return EINA_TRUE;
 
@@ -2630,6 +2641,12 @@ _eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, c
      {
         EINA_SAFETY_ON_FALSE_RETURN_VAL
           (desc_array->member_size == desc->subtype->value_size, EINA_FALSE);
+
+        if (desc_array == tmem->array)
+          {
+             tmem->subtype = desc->subtype;
+             return EINA_TRUE;
+          }
      }
 
    if (tmem->array)
@@ -2947,9 +2964,16 @@ _eina_value_type_list_pset(const Eina_Value_Type *type __UNUSED__, void *mem, co
    Eina_Value_List *tmem = mem;
    const Eina_Value_List *desc = ptr;
 
+   eina_error_set(0);
    if ((!tmem->subtype) && (!desc->subtype))
      return EINA_TRUE;
 
+   if ((tmem->list) && (tmem->list == desc->list))
+     {
+        tmem->subtype = desc->subtype;
+        return EINA_TRUE;
+     }
+
    _eina_value_type_list_flush_elements(tmem);
    tmem->subtype = desc->subtype;
    tmem->list = desc->list;
@@ -3304,9 +3328,16 @@ _eina_value_type_hash_pset(const Eina_Value_Type *type __UNUSED__, void *mem, co
    Eina_Value_Hash *tmem = mem;
    const Eina_Value_Hash *desc = ptr;
 
+   eina_error_set(0);
    if ((!tmem->subtype) && (!desc->subtype))
      return EINA_TRUE;
 
+   if ((tmem->hash) && (tmem->hash == desc->hash))
+     {
+        tmem->subtype = desc->subtype;
+        return EINA_TRUE;
+     }
+
    if (tmem->hash) _eina_value_type_hash_flush_elements(tmem);
 
    if (desc->hash)
@@ -3789,6 +3820,14 @@ _eina_value_type_blob_pset(const Eina_Value_Type *type __UNUSED__, void *mem, co
    Eina_Value_Blob *tmem = mem;
    const Eina_Value_Blob *desc = ptr;
 
+   eina_error_set(0);
+   if ((tmem->memory) && (tmem->memory == desc->memory))
+     {
+        tmem->ops = desc->ops;
+        tmem->size = desc->size;
+        return EINA_TRUE;
+     }
+
    if ((ops) && (ops->free))
      ops->free(ops, (void *)tmem->memory, tmem->size);
 
@@ -4287,15 +4326,18 @@ _eina_value_type_struct_pset(const Eina_Value_Type *type, void *mem, const void
         return EINA_FALSE;
      }
 
-   _eina_value_type_struct_flush(type, mem);
-
-   *tmem = *desc;
-   if (tmem->memory)
+   eina_error_set(0);
+   if ((tmem->memory) && (tmem->memory == desc->memory))
      {
-        eina_error_set(0);
+        tmem->desc = desc->desc;
         return EINA_TRUE;
      }
 
+   _eina_value_type_struct_flush(type, mem);
+
+   *tmem = *desc;
+   if (tmem->memory) return EINA_TRUE;
+
    ops = _eina_value_type_struct_ops_get(desc);
    if ((ops) && (ops->alloc))
      tmem->memory = ops->alloc(ops, tmem->desc);
@@ -4324,7 +4366,6 @@ _eina_value_type_struct_pset(const Eina_Value_Type *type, void *mem, const void
             goto error;
      }
 
-   eina_error_set(0);
    return EINA_TRUE;
 
  error:
@@ -4458,6 +4499,9 @@ _eina_value_type_model_pset(const Eina_Value_Type *type __UNUSED__, void *mem, c
    Eina_Model **tmem = mem;
    Eina_Model **p = (Eina_Model **)ptr;
 
+   eina_error_set(0);
+   if (*tmem == *p) return EINA_TRUE;
+
    if (*p) eina_model_ref(*p);
    if (*tmem) eina_model_unref(*tmem);