1
0
forked from aniani/vim

patch 8.2.1798: Vim9: trinary operator condition is too permissive

Problem:    Vim9: trinary operator condition is too permissive.
Solution:   Use tv_get_bool_chk().
This commit is contained in:
Bram Moolenaar
2020-10-04 16:06:05 +02:00
parent 6abd3dc257
commit 1310660557
10 changed files with 215 additions and 36 deletions

View File

@@ -4212,7 +4212,17 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
// the condition is a constant, we know whether the ? or the :
// expression is to be evaluated.
has_const_expr = TRUE;
const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
if (op_falsy)
const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
else
{
int error = FALSE;
const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
&error);
if (error)
return FAIL;
}
cctx->ctx_skip = save_skip == SKIP_YES ||
(op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
@@ -5637,6 +5647,23 @@ drop_scope(cctx_T *cctx)
vim_free(scope);
}
/*
* Check that the top of the type stack has a type that can be used as a
* condition. Give an error and return FAIL if not.
*/
static int
bool_on_stack(cctx_T *cctx)
{
garray_T *stack = &cctx->ctx_type_stack;
type_T *type;
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (type != &t_bool && type != &t_number && type != &t_any
&& need_type(type, &t_bool, -1, cctx, FALSE) == FAIL)
return FAIL;
return OK;
}
/*
* compile "if expr"
*
@@ -5689,8 +5716,14 @@ compile_if(char_u *arg, cctx_T *cctx)
clear_ppconst(&ppconst);
else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
{
int error = FALSE;
int v;
// The expression results in a constant.
cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
if (error)
return NULL;
cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
clear_ppconst(&ppconst);
}
else
@@ -5699,6 +5732,8 @@ compile_if(char_u *arg, cctx_T *cctx)
cctx->ctx_skip = SKIP_UNKNOWN;
if (generate_ppconst(cctx, &ppconst) == FAIL)
return NULL;
if (bool_on_stack(cctx) == FAIL)
return NULL;
}
scope = new_scope(cctx, IF_SCOPE);
@@ -5764,9 +5799,15 @@ compile_elseif(char_u *arg, cctx_T *cctx)
clear_ppconst(&ppconst);
else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
{
int error = FALSE;
int v;
// The expression results in a constant.
// TODO: how about nesting?
cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
if (error)
return NULL;
cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
clear_ppconst(&ppconst);
scope->se_u.se_if.is_if_label = -1;
}
@@ -5776,6 +5817,8 @@ compile_elseif(char_u *arg, cctx_T *cctx)
cctx->ctx_skip = SKIP_UNKNOWN;
if (generate_ppconst(cctx, &ppconst) == FAIL)
return NULL;
if (bool_on_stack(cctx) == FAIL)
return NULL;
// "where" is set when ":elseif", "else" or ":endif" is found
scope->se_u.se_if.is_if_label = instr->ga_len;
@@ -6037,6 +6080,9 @@ compile_while(char_u *arg, cctx_T *cctx)
if (compile_expr0(&p, cctx) == FAIL)
return NULL;
if (bool_on_stack(cctx) == FAIL)
return FAIL;
// "while_end" is set when ":endwhile" is found
if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
JUMP_IF_FALSE, cctx) == FAIL)