Compare commits

...

9 Commits

Author SHA1 Message Date
Bram Moolenaar
b1040dc11f patch 8.2.4976: Coverity complains about not restoring a saved value
Problem:    Coverity complains about not restoring a saved value.
Solution:   Restore value before handling error.
2022-05-18 11:00:48 +01:00
Bram Moolenaar
51f0bfb88a patch 8.2.4975: recursive command line loop may cause a crash
Problem:    Recursive command line loop may cause a crash.
Solution:   Limit recursion of getcmdline().
2022-05-17 20:11:02 +01:00
Bram Moolenaar
4748c4bd64 patch 8.2.4974: ":so" command may read after end of buffer
Problem:    ":so" command may read after end of buffer.
Solution:   Compute length of text properly.
2022-05-17 17:47:07 +01:00
Bram Moolenaar
bd3a9d2c94 patch 8.2.4973: Vim9: type error for list unpack mentions argument
Problem:    Vim9: type error for list unpack mentions argument.
Solution:   Mention variable. (close #10435)
2022-05-17 16:12:39 +01:00
Bram Moolenaar
1ff9c44267 patch 8.2.4972: Vim9: compilation fails when using dict member when skipping
Problem:    Vim9: compilation fails when using dict member when skipping.
Solution:   Do not generate ISN_USEDICT when skipping. (closes #10433)
2022-05-17 15:03:33 +01:00
Bram Moolenaar
40c141d333 patch 8.2.4971: Vim9: interpolated string seen as range
Problem:    Vim9: interpolated string seen as range.
Solution:   Recognize an interpolated string at the start of a command line.
            (closes #10434)
2022-05-17 13:14:23 +01:00
Bram Moolenaar
0d03263fd7 patch 8.2.4970: "eval 123" gives an error, "eval 'abc'" does not
Problem:    "eval 123" gives an error, "eval 'abc'" does not.
Solution:   Also give an error when evaluating only a string. (closes #10434)
2022-05-17 12:45:15 +01:00
Bram Moolenaar
7ce5b2b590 patch 8.2.4969: changing text in Visual mode may cause invalid memory access
Problem:    Changing text in Visual mode may cause invalid memory access.
Solution:   Check the Visual position after making a change.
2022-05-16 19:40:59 +01:00
Bram Moolenaar
60ae0e7149 patch 8.2.4968: reading past end of the line when C-indenting
Problem:    Reading past end of the line when C-indenting.
Solution:   Check for NUL.
2022-05-16 18:06:15 +01:00
24 changed files with 168 additions and 32 deletions

View File

@@ -548,6 +548,9 @@ changed_common(
curwin->w_changelistidx = curbuf->b_changelistlen;
}
if (VIsual_active)
check_visual_pos();
FOR_ALL_TAB_WINDOWS(tp, wp)
{
if (wp->w_buffer == curbuf)

View File

@@ -89,7 +89,7 @@ skip_string(char_u *p)
while (vim_isdigit(p[i - 1])) // '\000'
++i;
}
if (p[i] == '\'') // check for trailing '
if (p[i - 1] != NUL && p[i] == '\'') // check for trailing '
{
p += i;
continue;

View File

@@ -2541,16 +2541,8 @@ stop_insert(
// <C-S-Right> may have started Visual mode, adjust the position for
// deleted characters.
if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum)
{
int len = (int)STRLEN(ml_get_curline());
if (VIsual.col > len)
{
VIsual.col = len;
VIsual.coladd = 0;
}
}
if (VIsual_active)
check_visual_pos();
}
}
did_ai = FALSE;

View File

@@ -3551,7 +3551,8 @@ find_ex_command(
char_u *swp;
if (*eap->cmd == '&'
|| *eap->cmd == '$'
|| (eap->cmd[0] == '$'
&& eap->cmd[1] != '\'' && eap->cmd[1] != '"')
|| (eap->cmd[0] == '@'
&& (valid_yank_reg(eap->cmd[1], FALSE)
|| eap->cmd[1] == '@')))
@@ -3590,9 +3591,13 @@ find_ex_command(
// "'string'->func()" is an expression.
|| *eap->cmd == '\''
// '"string"->func()' is an expression.
|| (eap->cmd[0] == '0' && eap->cmd[1] == 'z')
// '"string"->func()' is an expression.
|| *eap->cmd == '"'
// '$"string"->func()' is an expression.
// "$'string'->func()" is an expression.
|| (eap->cmd[0] == '$'
&& (eap->cmd[1] == '\'' || eap->cmd[1] == '"'))
// '0z1234->func()' is an expression.
|| (eap->cmd[0] == '0' && eap->cmd[1] == 'z')
// "g:varname" is an expression.
|| eap->cmd[1] == ':'
)

View File

@@ -888,8 +888,8 @@ report_discard_pending(int pending, void *value)
}
/*
* Return TRUE if "arg" is only a variable, register, environment variable or
* option name.
* Return TRUE if "arg" is only a variable, register, environment variable,
* option name or string.
*/
int
cmd_is_name_only(char_u *arg)
@@ -904,6 +904,17 @@ cmd_is_name_only(char_u *arg)
if (*p != NUL)
++p;
}
else if (*p == '\'' || *p == '"')
{
int r;
if (*p == '"')
r = eval_string(&p, NULL, FALSE, FALSE);
else
r = eval_lit_string(&p, NULL, FALSE, FALSE);
if (r == FAIL)
return FALSE;
}
else
{
if (*p == '&')

View File

@@ -1581,6 +1581,7 @@ getcmdline_int(
int indent, // indent for inside conditionals
int clear_ccline) // clear ccline first
{
static int depth = 0; // call depth
int c;
int i;
int j;
@@ -1611,6 +1612,9 @@ getcmdline_int(
int cmdline_type;
int wild_type;
// one recursion level deeper
++depth;
if (ccline.cmdbuff != NULL)
{
// Being called recursively. Since ccline is global, we need to save
@@ -1641,6 +1645,13 @@ getcmdline_int(
if (init_ccline(firstc, indent) != OK)
goto theend; // out of memory
if (depth == 50)
{
// Somehow got into a loop recursively calling getcmdline(), bail out.
emsg(_(e_command_too_recursive));
goto theend;
}
ExpandInit(&xpc);
ccline.xpc = &xpc;
@@ -2576,6 +2587,7 @@ theend:
{
char_u *p = ccline.cmdbuff;
--depth;
if (did_save_ccline)
restore_cmdline(&save_ccline);
else

View File

@@ -622,6 +622,31 @@ check_cursor(void)
check_cursor_col();
}
/*
* Check if VIsual position is valid, correct it if not.
* Can be called when in Visual mode and a change has been made.
*/
void
check_visual_pos(void)
{
if (VIsual.lnum > curbuf->b_ml.ml_line_count)
{
VIsual.lnum = curbuf->b_ml.ml_line_count;
VIsual.col = 0;
VIsual.coladd = 0;
}
else
{
int len = (int)STRLEN(ml_get(VIsual.lnum));
if (VIsual.col > len)
{
VIsual.col = len;
VIsual.coladd = 0;
}
}
}
#if defined(FEAT_TEXTOBJ) || defined(PROTO)
/*
* Make sure curwin->w_cursor is not on the NUL at the end of the line.
@@ -2416,7 +2441,7 @@ get_user_name(char_u *buf, int len)
return OK;
}
#if defined(EXITFREE) || defined(PROTOS)
#if defined(EXITFREE) || defined(PROTO)
/*
* Free the memory allocated by get_user_name()
*/

View File

@@ -17,6 +17,7 @@ void check_cursor_lnum(void);
void check_cursor_col(void);
void check_cursor_col_win(win_T *win);
void check_cursor(void);
void check_visual_pos(void);
void adjust_cursor_col(void);
int leftcol_changed(void);
int copy_option_part(char_u **option, char_u *buf, int maxlen, char *sep_chars);

View File

@@ -9,9 +9,10 @@ vartype_T operator_type(type_T *type1, type_T *type2);
int generate_two_op(cctx_T *cctx, char_u *op);
int check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2);
int generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic);
int generate_CONCAT(cctx_T *cctx, int count);
int generate_2BOOL(cctx_T *cctx, int invert, int offset);
int generate_COND2BOOL(cctx_T *cctx);
int generate_TYPECHECK(cctx_T *cctx, type_T *expected, int offset, int argidx);
int generate_TYPECHECK(cctx_T *cctx, type_T *expected, int offset, int is_var, int argidx);
int generate_SETTYPE(cctx_T *cctx, type_T *expected);
int generate_tv_PUSH(cctx_T *cctx, typval_T *tv);
int generate_PUSHNR(cctx_T *cctx, varnumber_T number);
@@ -62,7 +63,6 @@ int generate_LEGACY_EVAL(cctx_T *cctx, char_u *line);
int generate_EXECCONCAT(cctx_T *cctx, int count);
int generate_RANGE(cctx_T *cctx, char_u *range);
int generate_UNPACK(cctx_T *cctx, int var_count, int semicolon);
int generate_CONCAT(cctx_T *cctx, int count);
int generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod);
int generate_undo_cmdmods(cctx_T *cctx);
int generate_store_var(cctx_T *cctx, assign_dest_T dest, int opt_flags, int vimvaridx, int scriptvar_idx, int scriptvar_sid, type_T *type, char_u *name);

View File

@@ -1965,6 +1965,7 @@ get_one_sourceline(source_cookie_T *sp)
break;
buf = (char_u *)ga.ga_data;
buf[ga.ga_len++] = NUL;
len = ga.ga_len;
}
else
{
@@ -1972,8 +1973,8 @@ get_one_sourceline(source_cookie_T *sp)
if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
sp->fp) == NULL)
break;
len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
}
len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
#ifdef USE_CRNL
// Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
// CTRL-Z by its own, or after a NL.

View File

@@ -5319,6 +5319,13 @@ func Test_cindent_change_multline()
close!
endfunc
" This was reading past the end of the line
func Test_cindent_check_funcdecl()
new
sil norm o0('\0=L
bwipe!
endfunc
func Test_cindent_scopedecls()
new
setl cindent ts=4 sw=4

View File

@@ -3392,4 +3392,16 @@ func Test_screenpos_and_completion()
call feedkeys(":let a\<C-R>=Check_completion()\<CR>\<Esc>", "xt")
endfunc
func Test_recursive_register()
let @= = ''
silent! ?e/
let caught = 'no'
try
normal //
catch /E169:/
let caught = 'yes'
endtry
call assert_equal('yes', caught)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -652,6 +652,17 @@ func Test_source_buffer_long_line()
norm300gr0
so
bwipe!
let lines =<< trim END
new
norm 10a0000000000ø00000000000
norm i0000000000000000000
silent! so
END
call writefile(lines, 'Xtest.vim')
source Xtest.vim
bwipe!
call delete('Xtest.vim')
endfunc

View File

@@ -697,6 +697,16 @@ def Test_use_register()
END
v9.CheckDefAndScriptFailure(lines, 'E1207:', 2)
$SomeEnv = ''
lines =<< trim END
eval 'value'
END
v9.CheckDefAndScriptFailure(lines, 'E1207:', 1)
lines =<< trim END
eval "value"
END
v9.CheckDefAndScriptFailure(lines, 'E1207:', 1)
enddef
def Test_environment_use_linebreak()

View File

@@ -581,10 +581,10 @@ def Test_disassemble_list_assign()
'\d CHECKTYPE list<any> stack\[-1\]\_s*' ..
'\d CHECKLEN >= 2\_s*' ..
'\d\+ ITEM 0\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\] arg 1\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\] var 1\_s*' ..
'\d\+ STORE $0\_s*' ..
'\d\+ ITEM 1\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\] arg 2\_s*' ..
'\d\+ CHECKTYPE string stack\[-1\] var 2\_s*' ..
'\d\+ STORE $1\_s*' ..
'\d\+ SLICE 2\_s*' ..
'\d\+ STORE $2\_s*' ..

View File

@@ -452,6 +452,12 @@ def Test_expr3()
g:vals = []
assert_equal(false, g:Record(1) && g:Record(true) && g:Record(0))
assert_equal([1, true, 0], g:vals)
var failed = false
if false && g:a == g:b.c
failed = true
endif
assert_false(failed)
END
v9.CheckDefAndScriptSuccess(lines)
enddef
@@ -3572,7 +3578,9 @@ def Test_expr8_method_call()
setline(1, ['first', 'last'])
'second'->append(1)
"third"->append(2)
assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
$"fourth"->append(3)
$'fifth'->append(4)
assert_equal(['first', 'second', 'third', 'fourth', 'fifth', 'last'], getline(1, '$'))
bwipe!
var bufnr = bufnr()

View File

@@ -2302,7 +2302,7 @@ def Test_for_loop_fails()
echo k v
endfor
END
v9.CheckDefExecAndScriptFailure(lines, ['E1013: Argument 1: type mismatch, expected job but got string', 'E1012: Type mismatch; expected job but got string'], 2)
v9.CheckDefExecAndScriptFailure(lines, ['E1163: Variable 1: type mismatch, expected job but got string', 'E1012: Type mismatch; expected job but got string'], 2)
lines =<< trim END
var i = 0

View File

@@ -1296,6 +1296,16 @@ func Test_visual_block_append_invalid_char()
set isprint&
endfunc
func Test_visual_block_with_substitute()
" this was reading beyond the end of the line
new
norm a0)
sil! norm  O
s/)
sil! norm 
bwipe!
endfunc
func Test_visual_reselect_with_count()
" this was causing an illegal memory access
let lines =<< trim END

View File

@@ -746,6 +746,24 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4976,
/**/
4975,
/**/
4974,
/**/
4973,
/**/
4972,
/**/
4971,
/**/
4970,
/**/
4969,
/**/
4968,
/**/
4967,
/**/

View File

@@ -296,6 +296,7 @@ typedef struct {
type_T *ct_type;
int8_T ct_off; // offset in stack, -1 is bottom
int8_T ct_arg_idx; // argument index or zero
int8_T ct_is_var; // when TRUE checking variable instead of arg
} checktype_T;
// arguments to ISN_STORENR

View File

@@ -412,7 +412,8 @@ need_type_where(
// If the actual type can be the expected type add a runtime check.
if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected))
{
generate_TYPECHECK(cctx, expected, offset, where.wt_index);
generate_TYPECHECK(cctx, expected, offset,
where.wt_variable, where.wt_index);
return OK;
}

View File

@@ -4652,13 +4652,17 @@ exec_instructions(ectx_T *ectx)
case ISN_CHECKTYPE:
{
checktype_T *ct = &iptr->isn_arg.type;
int save_wt_variable = ectx->ec_where.wt_variable;
int r;
tv = STACK_TV_BOT((int)ct->ct_off);
SOURCING_LNUM = iptr->isn_lnum;
if (!ectx->ec_where.wt_variable)
ectx->ec_where.wt_index = ct->ct_arg_idx;
if (check_typval_type(ct->ct_type, tv, ectx->ec_where)
== FAIL)
ectx->ec_where.wt_variable = ct->ct_is_var;
r = check_typval_type(ct->ct_type, tv, ectx->ec_where);
ectx->ec_where.wt_variable = save_wt_variable;
if (r == FAIL)
goto on_error;
if (!ectx->ec_where.wt_variable)
ectx->ec_where.wt_index = 0;
@@ -6114,18 +6118,19 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_CHECKTYPE:
{
checktype_T *ct = &iptr->isn_arg.type;
char *tofree;
checktype_T *ct = &iptr->isn_arg.type;
char *tofree;
if (ct->ct_arg_idx == 0)
smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
type_name(ct->ct_type, &tofree),
(int)ct->ct_off);
else
smsg("%s%4d CHECKTYPE %s stack[%d] arg %d",
smsg("%s%4d CHECKTYPE %s stack[%d] %s %d",
pfx, current,
type_name(ct->ct_type, &tofree),
(int)ct->ct_off,
ct->ct_is_var ? "var": "arg",
(int)ct->ct_arg_idx);
vim_free(tofree);
break;

View File

@@ -2102,7 +2102,8 @@ compile_subscript(
// Turn "dict.Func" into a partial for "Func" bound to "dict".
// This needs to be done at runtime to be able to check the type.
if (keeping_dict && generate_instr(cctx, ISN_USEDICT) == NULL)
if (keeping_dict && cctx->ctx_skip != SKIP_YES
&& generate_instr(cctx, ISN_USEDICT) == NULL)
return FAIL;
return OK;

View File

@@ -542,6 +542,7 @@ generate_TYPECHECK(
cctx_T *cctx,
type_T *expected,
int offset,
int is_var,
int argidx)
{
isn_T *isn;
@@ -551,6 +552,7 @@ generate_TYPECHECK(
return FAIL;
isn->isn_arg.type.ct_type = alloc_type(expected);
isn->isn_arg.type.ct_off = (int8_T)offset;
isn->isn_arg.type.ct_is_var = is_var;
isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
// type becomes expected
@@ -1437,7 +1439,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
if (maptype != NULL && maptype[0].type_decl->tt_member != NULL
&& maptype[0].type_decl->tt_member != &t_any)
// Check that map() didn't change the item types.
generate_TYPECHECK(cctx, maptype[0].type_decl, -1, 1);
generate_TYPECHECK(cctx, maptype[0].type_decl, -1, FALSE, 1);
return OK;
}