changeset 25290:8b7ea875afed v8.2.3182

patch 8.2.3182: Vim9: crash when using removing items from a constant list Commit: https://github.com/vim/vim/commit/885971e2f5eabc4108e083086c1d6d0a31a2782f Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 18 22:25:29 2021 +0200 patch 8.2.3182: Vim9: crash when using removing items from a constant list Problem: Vim9: crash when using removing items from a constant list. (Yegappan Lakshmanan) Solution: When a list was allocated with items copy them.
author Bram Moolenaar <Bram@vim.org>
date Sun, 18 Jul 2021 22:30:03 +0200
parents 82de8cfb8bdc
children ef3222de6d9c
files src/list.c src/testdir/test_vim9_builtin.vim src/version.c
diffstat 3 files changed, 34 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/list.c
+++ b/src/list.c
@@ -1566,12 +1566,32 @@ list_remove(typval_T *argvars, typval_T 
 		    vimlist_remove(l, item, item2);
 		    if (rettv_list_alloc(rettv) == OK)
 		    {
-			l = rettv->vval.v_list;
-			l->lv_first = item;
-			l->lv_u.mat.lv_last = item2;
-			item->li_prev = NULL;
-			item2->li_next = NULL;
-			l->lv_len = cnt;
+			list_T *rl = rettv->vval.v_list;
+
+			if (l->lv_with_items > 0)
+			{
+			    // need to copy the list items and move the value
+			    while (item != NULL)
+			    {
+				li = listitem_alloc();
+				if (li == NULL)
+				    return;
+				li->li_tv = item->li_tv;
+				init_tv(&item->li_tv);
+				list_append(rl, li);
+				if (item == item2)
+				    break;
+				item = item->li_next;
+			    }
+			}
+			else
+			{
+			    rl->lv_first = item;
+			    rl->lv_u.mat.lv_last = item2;
+			    item->li_prev = NULL;
+			    item2->li_next = NULL;
+			    rl->lv_len = cnt;
+			}
 		    }
 		}
 	    }
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -2083,6 +2083,12 @@ def Test_remote_startserver()
   CheckDefFailure(['remote_startserver({})'], 'E1013: Argument 1: type mismatch, expected string but got dict<unknown>')
 enddef
 
+def Test_remove_const_list()
+  var l: list<number> = [1, 2, 3, 4]
+  assert_equal([1, 2], remove(l, 0, 1))
+  assert_equal([3, 4], l)
+enddef
+
 def Test_remove_return_type()
   var l = remove({one: [1, 2], two: [3, 4]}, 'one')
   var res = 0
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3182,
+/**/
     3181,
 /**/
     3180,