Patch 8.2.1001

4 views
Skip to first unread message

Bram Moolenaar

unread,
Jun 18, 2020, 12:27:05 PM6/18/20
to vim...@googlegroups.com

Patch 8.2.1001
Problem: Vim9: crash with nested "if" and assignment.
Solution: Skip more of the assignment. Do not set ctx_skip when code is
reachable.
Files: src/vim9compile.c, src/testdir/test_vim9_script.vim


*** ../vim-8.2.1000/src/vim9compile.c 2020-06-16 11:34:38.314223444 +0200
--- src/vim9compile.c 2020-06-18 18:13:43.064410926 +0200
***************
*** 5067,5074 ****

if (!heredoc)
{
! if (oplen > 0)
{
// For "var = expr" evaluate the expression.
if (var_count == 0)
{
--- 5067,5085 ----

if (!heredoc)
{
! if (cctx->ctx_skip == TRUE)
{
+ if (oplen > 0 && var_count == 0)
+ {
+ // skip over the "=" and the expression
+ p = skipwhite(op + oplen);
+ compile_expr0(&p, cctx);
+ }
+ }
+ else if (oplen > 0)
+ {
+ type_T *stacktype;
+
// For "var = expr" evaluate the expression.
if (var_count == 0)
{
***************
*** 5113,5164 ****
return FAIL;
}

! if (cctx->ctx_skip != TRUE)
{
! type_T *stacktype;
!
! stacktype = stack->ga_len == 0 ? &t_void
! : ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (lvar != NULL && (is_decl || !has_type))
{
! if (new_local && !has_type)
{
! if (stacktype->tt_type == VAR_VOID)
! {
! emsg(_(e_cannot_use_void));
! goto theend;
! }
! else
! {
! // An empty list or dict has a &t_void member,
! // for a variable that implies &t_any.
! if (stacktype == &t_list_empty)
! lvar->lv_type = &t_list_any;
! else if (stacktype == &t_dict_empty)
! lvar->lv_type = &t_dict_any;
! else
! lvar->lv_type = stacktype;
! }
}
else
{
! type_T *use_type = lvar->lv_type;

! if (has_index)
! {
! use_type = use_type->tt_member;
! if (use_type == NULL)
! use_type = &t_void;
! }
! if (need_type(stacktype, use_type, -1, cctx)
! == FAIL)
! goto theend;
}
}
- else if (*p != '=' && need_type(stacktype, member_type, -1,
- cctx) == FAIL)
- goto theend;
}
}
else if (cmdidx == CMD_const)
{
--- 5124,5170 ----
return FAIL;
}

! stacktype = stack->ga_len == 0 ? &t_void
! : ((type_T **)stack->ga_data)[stack->ga_len - 1];
! if (lvar != NULL && (is_decl || !has_type))
{
! if (new_local && !has_type)
{
! if (stacktype->tt_type == VAR_VOID)
{
! emsg(_(e_cannot_use_void));
! goto theend;
}
else
{
! // An empty list or dict has a &t_void member,
! // for a variable that implies &t_any.
! if (stacktype == &t_list_empty)
! lvar->lv_type = &t_list_any;
! else if (stacktype == &t_dict_empty)
! lvar->lv_type = &t_dict_any;
! else
! lvar->lv_type = stacktype;
! }
! }
! else
! {
! type_T *use_type = lvar->lv_type;

! if (has_index)
! {
! use_type = use_type->tt_member;
! if (use_type == NULL)
! use_type = &t_void;
}
+ if (need_type(stacktype, use_type, -1, cctx)
+ == FAIL)
+ goto theend;
}
}
+ else if (*p != '=' && need_type(stacktype, member_type, -1,
+ cctx) == FAIL)
+ goto theend;
}
else if (cmdidx == CMD_const)
{
***************
*** 5220,5225 ****
--- 5226,5235 ----
end = p;
}

+ // no need to parse more when skipping
+ if (cctx->ctx_skip == TRUE)
+ break;
+
if (oplen > 0 && *op != '=')
{
type_T *expected = &t_number;
***************
*** 5806,5812 ****
}
// Fill in the "end" label in jumps at the end of the blocks.
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
! cctx->ctx_skip = FALSE;

drop_scope(cctx);
return arg;
--- 5816,5823 ----
}
// Fill in the "end" label in jumps at the end of the blocks.
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
! // TODO: this should restore the value from before the :if
! cctx->ctx_skip = MAYBE;

drop_scope(cctx);
return arg;
*** ../vim-8.2.1000/src/testdir/test_vim9_script.vim 2020-06-17 20:03:33.150287410 +0200
--- src/testdir/test_vim9_script.vim 2020-06-18 17:55:39.971828998 +0200
***************
*** 1162,1167 ****
--- 1162,1187 ----
call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
enddef

+ def RunNested(i: number): number
+ let x: number = 0
+ if i % 2
+ if 1
+ " comment
+ else
+ " comment
+ endif
+ x += 1
+ else
+ x += 1000
+ endif
+ return x
+ enddef
+
+ def Test_nested_if()
+ assert_equal(1, RunNested(1))
+ assert_equal(1000, RunNested(2))
+ enddef
+
def Test_execute_cmd()
new
setline(1, 'default')
*** ../vim-8.2.1000/src/version.c 2020-06-18 17:28:36.857031469 +0200
--- src/version.c 2020-06-18 18:20:54.656037243 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1001,
/**/

--
MESKIMEN'S LAW
There's never time to do it right, but always time to do it over.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages