mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.1.0445: Coverity warning after 9.1.0440
Problem: Coverity warning after 9.1.0440 Solution: Fix Coverity warning, add a test and reduce the calls to clear_tv() (Yegappan Lakshmanan). closes: #14845 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
dff55a3358
commit
dbac0da631
169
src/eval.c
169
src/eval.c
@ -1317,10 +1317,7 @@ get_lval_dict_item(
|
|||||||
// "[key]": get key from "var1"
|
// "[key]": get key from "var1"
|
||||||
key = tv_get_string_chk(var1); // is number or string
|
key = tv_get_string_chk(var1); // is number or string
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
{
|
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lp->ll_list = NULL;
|
lp->ll_list = NULL;
|
||||||
lp->ll_object = NULL;
|
lp->ll_object = NULL;
|
||||||
@ -1331,10 +1328,7 @@ get_lval_dict_item(
|
|||||||
{
|
{
|
||||||
lp->ll_tv->vval.v_dict = dict_alloc();
|
lp->ll_tv->vval.v_dict = dict_alloc();
|
||||||
if (lp->ll_tv->vval.v_dict == NULL)
|
if (lp->ll_tv->vval.v_dict == NULL)
|
||||||
{
|
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
|
||||||
++lp->ll_tv->vval.v_dict->dv_refcount;
|
++lp->ll_tv->vval.v_dict->dv_refcount;
|
||||||
}
|
}
|
||||||
lp->ll_dict = lp->ll_tv->vval.v_dict;
|
lp->ll_dict = lp->ll_tv->vval.v_dict;
|
||||||
@ -1363,10 +1357,7 @@ get_lval_dict_item(
|
|||||||
if (len != -1)
|
if (len != -1)
|
||||||
key[len] = prevval;
|
key[len] = prevval;
|
||||||
if (wrong)
|
if (wrong)
|
||||||
{
|
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lp->ll_valtype != NULL)
|
if (lp->ll_valtype != NULL)
|
||||||
@ -1380,7 +1371,6 @@ get_lval_dict_item(
|
|||||||
|| &lp->ll_dict->dv_hashtab == get_funccal_args_ht())
|
|| &lp->ll_dict->dv_hashtab == get_funccal_args_ht())
|
||||||
{
|
{
|
||||||
semsg(_(e_illegal_variable_name_str), name);
|
semsg(_(e_illegal_variable_name_str), name);
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,14 +1379,12 @@ get_lval_dict_item(
|
|||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
semsg(_(e_key_not_present_in_dictionary_str), key);
|
semsg(_(e_key_not_present_in_dictionary_str), key);
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
}
|
||||||
if (len == -1)
|
if (len == -1)
|
||||||
lp->ll_newkey = vim_strsave(key);
|
lp->ll_newkey = vim_strsave(key);
|
||||||
else
|
else
|
||||||
lp->ll_newkey = vim_strnsave(key, len);
|
lp->ll_newkey = vim_strnsave(key, len);
|
||||||
clear_tv(var1);
|
|
||||||
if (lp->ll_newkey == NULL)
|
if (lp->ll_newkey == NULL)
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
|
||||||
@ -1407,12 +1395,8 @@ get_lval_dict_item(
|
|||||||
else if ((flags & GLV_READ_ONLY) == 0
|
else if ((flags & GLV_READ_ONLY) == 0
|
||||||
&& (var_check_ro(lp->ll_di->di_flags, name, FALSE)
|
&& (var_check_ro(lp->ll_di->di_flags, name, FALSE)
|
||||||
|| var_check_lock(lp->ll_di->di_flags, name, FALSE)))
|
|| var_check_lock(lp->ll_di->di_flags, name, FALSE)))
|
||||||
{
|
|
||||||
clear_tv(var1);
|
|
||||||
return GLV_FAIL;
|
return GLV_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
clear_tv(var1);
|
|
||||||
lp->ll_tv = &lp->ll_di->di_tv;
|
lp->ll_tv = &lp->ll_di->di_tv;
|
||||||
|
|
||||||
return GLV_OK;
|
return GLV_OK;
|
||||||
@ -1445,17 +1429,12 @@ get_lval_blob(
|
|||||||
else
|
else
|
||||||
// is number or string
|
// is number or string
|
||||||
lp->ll_n1 = (long)tv_get_number(var1);
|
lp->ll_n1 = (long)tv_get_number(var1);
|
||||||
clear_tv(var1);
|
|
||||||
|
|
||||||
if (check_blob_index(bloblen, lp->ll_n1, quiet) == FAIL)
|
if (check_blob_index(bloblen, lp->ll_n1, quiet) == FAIL)
|
||||||
{
|
|
||||||
clear_tv(var2);
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
|
||||||
if (lp->ll_range && !lp->ll_empty2)
|
if (lp->ll_range && !lp->ll_empty2)
|
||||||
{
|
{
|
||||||
lp->ll_n2 = (long)tv_get_number(var2);
|
lp->ll_n2 = (long)tv_get_number(var2);
|
||||||
clear_tv(var2);
|
|
||||||
if (check_blob_range(bloblen, lp->ll_n1, lp->ll_n2, quiet) == FAIL)
|
if (check_blob_range(bloblen, lp->ll_n1, lp->ll_n2, quiet) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@ -1499,7 +1478,6 @@ get_lval_list(
|
|||||||
else
|
else
|
||||||
// is number or string
|
// is number or string
|
||||||
lp->ll_n1 = (long)tv_get_number(var1);
|
lp->ll_n1 = (long)tv_get_number(var1);
|
||||||
clear_tv(var1);
|
|
||||||
|
|
||||||
lp->ll_dict = NULL;
|
lp->ll_dict = NULL;
|
||||||
lp->ll_object = NULL;
|
lp->ll_object = NULL;
|
||||||
@ -1508,10 +1486,7 @@ get_lval_list(
|
|||||||
lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1,
|
lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1,
|
||||||
(flags & GLV_ASSIGN_WITH_OP) == 0, quiet);
|
(flags & GLV_ASSIGN_WITH_OP) == 0, quiet);
|
||||||
if (lp->ll_li == NULL)
|
if (lp->ll_li == NULL)
|
||||||
{
|
|
||||||
clear_tv(var2);
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
if (lp->ll_valtype != NULL && !lp->ll_range)
|
if (lp->ll_valtype != NULL && !lp->ll_range)
|
||||||
// use the type of the member
|
// use the type of the member
|
||||||
@ -1527,7 +1502,6 @@ get_lval_list(
|
|||||||
{
|
{
|
||||||
lp->ll_n2 = (long)tv_get_number(var2);
|
lp->ll_n2 = (long)tv_get_number(var2);
|
||||||
// is number or string
|
// is number or string
|
||||||
clear_tv(var2);
|
|
||||||
if (check_range_index_two(lp->ll_list,
|
if (check_range_index_two(lp->ll_list,
|
||||||
&lp->ll_n1, lp->ll_li, &lp->ll_n2, quiet) == FAIL)
|
&lp->ll_n1, lp->ll_li, &lp->ll_n2, quiet) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@ -1650,10 +1624,71 @@ get_lval_class_or_obj(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether dot (".") is allowed after the variable "name" with type
|
||||||
|
* "v_type". Only Dict, Class and Object types support a dot after the name.
|
||||||
|
* Returns TRUE if dot is allowed after the name.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dot_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
|
||||||
|
{
|
||||||
|
if (v_type != VAR_DICT && v_type != VAR_OBJECT && v_type != VAR_CLASS)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_dot_not_allowed_after_str_str),
|
||||||
|
vartype_name(v_type), name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether left bracket ("[") is allowed after the variable "name" with
|
||||||
|
* type "v_type". Only Dict, List and Blob types support a bracket after the
|
||||||
|
* variable name. Returns TRUE if bracket is allowed after the name.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
bracket_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
|
||||||
|
{
|
||||||
|
if (v_type == VAR_CLASS || v_type == VAR_OBJECT)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_index_not_allowed_after_str_str),
|
||||||
|
vartype_name(v_type), name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether the variable "name" with type "v_type" can be followed by an
|
||||||
|
* index. Only Dict, List, Blob, Object and Class types support indexing.
|
||||||
|
* Returns TRUE if indexing is allowed after the name.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
index_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
|
||||||
|
{
|
||||||
|
if (v_type != VAR_LIST && v_type != VAR_DICT && v_type != VAR_BLOB &&
|
||||||
|
v_type != VAR_OBJECT && v_type != VAR_CLASS)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_index_not_allowed_after_str_str),
|
||||||
|
vartype_name(v_type), name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the lval of a list/dict/blob/object/class subitem starting at "p". Loop
|
* Get the lval of a list/dict/blob/object/class subitem starting at "p". Loop
|
||||||
* until no more [idx] or .key is following.
|
* until no more [idx] or .key is following.
|
||||||
*
|
*
|
||||||
|
* If "rettv" is not NULL it points to the value to be assigned.
|
||||||
|
* "unlet" is TRUE for ":unlet".
|
||||||
|
*
|
||||||
* Returns a pointer to the character after the subscript on success or NULL on
|
* Returns a pointer to the character after the subscript on success or NULL on
|
||||||
* failure.
|
* failure.
|
||||||
*/
|
*/
|
||||||
@ -1676,6 +1711,7 @@ get_lval_subscript(
|
|||||||
typval_T var1;
|
typval_T var1;
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
int empty1 = FALSE;
|
int empty1 = FALSE;
|
||||||
|
int rc = FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop until no more [idx] or .key is following.
|
* Loop until no more [idx] or .key is following.
|
||||||
@ -1687,26 +1723,14 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
vartype_T v_type = lp->ll_tv->v_type;
|
vartype_T v_type = lp->ll_tv->v_type;
|
||||||
|
|
||||||
if (*p == '.' && v_type != VAR_DICT
|
if (*p == '.' && !dot_allowed_after_type(name, v_type, quiet))
|
||||||
&& v_type != VAR_OBJECT
|
goto done;
|
||||||
&& v_type != VAR_CLASS)
|
|
||||||
{
|
if (*p == '[' && !bracket_allowed_after_type(name, v_type, quiet))
|
||||||
if (!quiet)
|
goto done;
|
||||||
semsg(_(e_dot_not_allowed_after_str_str),
|
|
||||||
vartype_name(v_type), name);
|
if (!index_allowed_after_type(name, v_type, quiet))
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
|
||||||
if (v_type != VAR_LIST
|
|
||||||
&& v_type != VAR_DICT
|
|
||||||
&& v_type != VAR_BLOB
|
|
||||||
&& v_type != VAR_OBJECT
|
|
||||||
&& v_type != VAR_CLASS)
|
|
||||||
{
|
|
||||||
if (!quiet)
|
|
||||||
semsg(_(e_index_not_allowed_after_str_str),
|
|
||||||
vartype_name(v_type), name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A NULL list/blob works like an empty list/blob, allocate one now.
|
// A NULL list/blob works like an empty list/blob, allocate one now.
|
||||||
int r = OK;
|
int r = OK;
|
||||||
@ -1715,13 +1739,13 @@ get_lval_subscript(
|
|||||||
else if (v_type == VAR_BLOB && lp->ll_tv->vval.v_blob == NULL)
|
else if (v_type == VAR_BLOB && lp->ll_tv->vval.v_blob == NULL)
|
||||||
r = rettv_blob_alloc(lp->ll_tv);
|
r = rettv_blob_alloc(lp->ll_tv);
|
||||||
if (r == FAIL)
|
if (r == FAIL)
|
||||||
return NULL;
|
goto done;
|
||||||
|
|
||||||
if (lp->ll_range)
|
if (lp->ll_range)
|
||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
emsg(_(e_slice_must_come_last));
|
emsg(_(e_slice_must_come_last));
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
#ifdef LOG_LOCKVAR
|
#ifdef LOG_LOCKVAR
|
||||||
ch_log(NULL, "LKVAR: get_lval() loop: p: %s, type: %s", p,
|
ch_log(NULL, "LKVAR: get_lval() loop: p: %s, type: %s", p,
|
||||||
@ -1757,7 +1781,7 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
emsg(_(e_cannot_use_empty_key_for_dictionary));
|
emsg(_(e_cannot_use_empty_key_for_dictionary));
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
p = key + len;
|
p = key + len;
|
||||||
}
|
}
|
||||||
@ -1771,13 +1795,10 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
empty1 = FALSE;
|
empty1 = FALSE;
|
||||||
if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) // recursive!
|
if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) // recursive!
|
||||||
return NULL;
|
goto done;
|
||||||
if (tv_get_string_chk(&var1) == NULL)
|
if (tv_get_string_chk(&var1) == NULL)
|
||||||
{
|
|
||||||
// not a number or string
|
// not a number or string
|
||||||
clear_tv(&var1);
|
goto done;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1788,8 +1809,7 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
emsg(_(e_cannot_slice_dictionary));
|
emsg(_(e_cannot_slice_dictionary));
|
||||||
clear_tv(&var1);
|
goto done;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (rettv != NULL
|
if (rettv != NULL
|
||||||
&& !(rettv->v_type == VAR_LIST
|
&& !(rettv->v_type == VAR_LIST
|
||||||
@ -1799,8 +1819,7 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
emsg(_(e_slice_requires_list_or_blob_value));
|
emsg(_(e_slice_requires_list_or_blob_value));
|
||||||
clear_tv(&var1);
|
goto done;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
p = skipwhite(p + 1);
|
p = skipwhite(p + 1);
|
||||||
if (*p == ']')
|
if (*p == ']')
|
||||||
@ -1810,17 +1829,10 @@ get_lval_subscript(
|
|||||||
lp->ll_empty2 = FALSE;
|
lp->ll_empty2 = FALSE;
|
||||||
// recursive!
|
// recursive!
|
||||||
if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
|
if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
|
||||||
{
|
goto done;
|
||||||
clear_tv(&var1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (tv_get_string_chk(&var2) == NULL)
|
if (tv_get_string_chk(&var2) == NULL)
|
||||||
{
|
|
||||||
// not a number or string
|
// not a number or string
|
||||||
clear_tv(&var1);
|
goto done;
|
||||||
clear_tv(&var2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lp->ll_range = TRUE;
|
lp->ll_range = TRUE;
|
||||||
}
|
}
|
||||||
@ -1831,9 +1843,7 @@ get_lval_subscript(
|
|||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
emsg(_(e_missing_closing_square_brace));
|
emsg(_(e_missing_closing_square_brace));
|
||||||
clear_tv(&var1);
|
goto done;
|
||||||
clear_tv(&var2);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip to past ']'.
|
// Skip to past ']'.
|
||||||
@ -1854,32 +1864,41 @@ get_lval_subscript(
|
|||||||
glv_status = get_lval_dict_item(name, lp, key, len, &p, &var1,
|
glv_status = get_lval_dict_item(name, lp, key, len, &p, &var1,
|
||||||
flags, unlet, rettv);
|
flags, unlet, rettv);
|
||||||
if (glv_status == GLV_FAIL)
|
if (glv_status == GLV_FAIL)
|
||||||
return NULL;
|
goto done;
|
||||||
if (glv_status == GLV_STOP)
|
if (glv_status == GLV_STOP)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (v_type == VAR_BLOB)
|
else if (v_type == VAR_BLOB)
|
||||||
{
|
{
|
||||||
if (get_lval_blob(lp, &var1, &var2, empty1, quiet) == FAIL)
|
if (get_lval_blob(lp, &var1, &var2, empty1, quiet) == FAIL)
|
||||||
return NULL;
|
goto done;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (v_type == VAR_LIST)
|
else if (v_type == VAR_LIST)
|
||||||
{
|
{
|
||||||
if (get_lval_list(lp, &var1, &var2, empty1, flags, quiet) == FAIL)
|
if (get_lval_list(lp, &var1, &var2, empty1, flags, quiet) == FAIL)
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
else // v_type == VAR_CLASS || v_type == VAR_OBJECT
|
else // v_type == VAR_CLASS || v_type == VAR_OBJECT
|
||||||
{
|
{
|
||||||
if (get_lval_class_or_obj(cl_exec, v_type, lp, key, p, flags,
|
if (get_lval_class_or_obj(cl_exec, v_type, lp, key, p, flags,
|
||||||
quiet) == FAIL)
|
quiet) == FAIL)
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_tv(&var1);
|
||||||
|
clear_tv(&var2);
|
||||||
|
var1.v_type = VAR_UNKNOWN;
|
||||||
|
var2.v_type = VAR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = OK;
|
||||||
|
|
||||||
|
done:
|
||||||
clear_tv(&var1);
|
clear_tv(&var1);
|
||||||
return p;
|
clear_tv(&var2);
|
||||||
|
return rc == OK ? p : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -10724,4 +10724,24 @@ def Test_class_definition_in_a_function()
|
|||||||
v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
|
v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Test for using [] with a class and an object
|
||||||
|
def Test_class_object_index()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
A[10] = 1
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E689: Index not allowed after a class: A[10] = 1', 4)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
class A
|
||||||
|
endclass
|
||||||
|
var a = A.new()
|
||||||
|
a[10] = 1
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5)
|
||||||
|
enddef
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
445,
|
||||||
/**/
|
/**/
|
||||||
444,
|
444,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user