From e4075f361fe842821ba2bb68adba860f3bd07e58 Mon Sep 17 00:00:00 2001 From: barbieri Date: Fri, 10 Feb 2012 22:03:48 +0000 Subject: [PATCH] value: be safer on reset of existing values. 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 | 27 +++++++++----- src/lib/eina_value.c | 80 +++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 27 deletions(-) diff --git a/src/include/eina_inline_value.x b/src/include/eina_inline_value.x index 6f43c45..2d5f336 100644 --- a/src/include/eina_inline_value.x +++ b/src/include/eina_inline_value.x @@ -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; } diff --git a/src/lib/eina_value.c b/src/lib/eina_value.c index a4c6428..512591b 100644 --- a/src/lib/eina_value.c +++ b/src/lib/eina_value.c @@ -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); -- 2.7.4