Fix warnings: eval.c: clear_tv(): Bad free: RI.

Problem    : Bad free @ 16076.
Diagnostic : Real issue.
Rationale  : A non-allocated string is set at 4127, which later on can
             be tried to be freed if aborting.
Resolution : Detect particular case (func with empty name) and don't
             free in that case.
             Another solution (use allocated string) was tried before,
             but it produced a leak difficult to solve.
             Finally applied solution works, but it produces a new false
             positive warning (Np dereference at 13763), deactivated by
             `assert(ptrs[i].item->li_next)`.
This commit is contained in:
Eliseo Martínez 2014-11-17 10:05:08 +01:00
parent ece19651c6
commit eb15d8777b

View File

@ -178,6 +178,8 @@ static char *e_nofunc = N_("E130: Unknown function: %s");
static char *e_illvar = N_("E461: Illegal variable name: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s");
static char *e_float_as_string = N_("E806: using Float as a String"); static char *e_float_as_string = N_("E806: using Float as a String");
static char_u * const empty_string = (char_u *)"";
static dictitem_T globvars_var; /* variable used for g: */ static dictitem_T globvars_var; /* variable used for g: */
#define globvarht globvardict.dv_hashtab #define globvarht globvardict.dv_hashtab
@ -4124,7 +4126,7 @@ eval7 (
* get_func_tv, but it's needed in handle_subscript() to parse * get_func_tv, but it's needed in handle_subscript() to parse
* what follows. So set it here. */ * what follows. So set it here. */
if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') { if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') {
rettv->vval.v_string = (char_u *)""; rettv->vval.v_string = empty_string;
rettv->v_type = VAR_FUNC; rettv->v_type = VAR_FUNC;
} }
@ -13799,6 +13801,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
if (!item_compare_func_err) { if (!item_compare_func_err) {
while (--i >= 0) { while (--i >= 0) {
assert(ptrs[i].item->li_next);
li = ptrs[i].item->li_next; li = ptrs[i].item->li_next;
ptrs[i].item->li_next = li->li_next; ptrs[i].item->li_next = li->li_next;
if (li->li_next != NULL) { if (li->li_next != NULL) {
@ -16134,7 +16137,11 @@ void clear_tv(typval_T *varp)
switch (varp->v_type) { switch (varp->v_type) {
case VAR_FUNC: case VAR_FUNC:
func_unref(varp->vval.v_string); func_unref(varp->vval.v_string);
/*FALLTHROUGH*/ if (varp->vval.v_string != empty_string) {
free(varp->vval.v_string);
}
varp->vval.v_string = NULL;
break;
case VAR_STRING: case VAR_STRING:
free(varp->vval.v_string); free(varp->vval.v_string);
varp->vval.v_string = NULL; varp->vval.v_string = NULL;