mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 8.2.2738: extending a list with itself can give wrong result
Problem: Extending a list with itself can give wrong result. Solution: Remember the item before where the insertion happens and skip to after the already inserted items. (closes #1112)
This commit is contained in:
@@ -894,6 +894,7 @@ list_extend(list_T *l1, list_T *l2, listitem_T *bef)
|
|||||||
{
|
{
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
int todo;
|
int todo;
|
||||||
|
listitem_T *bef_prev;
|
||||||
|
|
||||||
// NULL list is equivalent to an empty list: nothing to do.
|
// NULL list is equivalent to an empty list: nothing to do.
|
||||||
if (l2 == NULL || l2->lv_len == 0)
|
if (l2 == NULL || l2->lv_len == 0)
|
||||||
@@ -903,9 +904,15 @@ list_extend(list_T *l1, list_T *l2, listitem_T *bef)
|
|||||||
CHECK_LIST_MATERIALIZE(l1);
|
CHECK_LIST_MATERIALIZE(l1);
|
||||||
CHECK_LIST_MATERIALIZE(l2);
|
CHECK_LIST_MATERIALIZE(l2);
|
||||||
|
|
||||||
|
// When exending a list with itself, at some point we run into the item
|
||||||
|
// that was before "bef" and need to skip over the already inserted items
|
||||||
|
// to "bef".
|
||||||
|
bef_prev = bef == NULL ? NULL : bef->li_prev;
|
||||||
|
|
||||||
// We also quit the loop when we have inserted the original item count of
|
// We also quit the loop when we have inserted the original item count of
|
||||||
// the list, avoid a hang when we extend a list with itself.
|
// the list, avoid a hang when we extend a list with itself.
|
||||||
for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
|
for (item = l2->lv_first; item != NULL && --todo >= 0;
|
||||||
|
item = item == bef_prev ? bef : item->li_next)
|
||||||
if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
|
if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
return OK;
|
return OK;
|
||||||
|
@@ -862,6 +862,20 @@ func Test_listdict_extend()
|
|||||||
|
|
||||||
" Extend g: dictionary with an invalid variable name
|
" Extend g: dictionary with an invalid variable name
|
||||||
call assert_fails("call extend(g:, {'-!' : 10})", 'E461:')
|
call assert_fails("call extend(g:, {'-!' : 10})", 'E461:')
|
||||||
|
|
||||||
|
" Extend a list with itself.
|
||||||
|
let l = [1, 5, 7]
|
||||||
|
call extend(l, l, 0)
|
||||||
|
call assert_equal([1, 5, 7, 1, 5, 7], l)
|
||||||
|
let l = [1, 5, 7]
|
||||||
|
call extend(l, l, 1)
|
||||||
|
call assert_equal([1, 1, 5, 7, 5, 7], l)
|
||||||
|
let l = [1, 5, 7]
|
||||||
|
call extend(l, l, 2)
|
||||||
|
call assert_equal([1, 5, 1, 5, 7, 7], l)
|
||||||
|
let l = [1, 5, 7]
|
||||||
|
call extend(l, l, 3)
|
||||||
|
call assert_equal([1, 5, 7, 1, 5, 7], l)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_listdict_extendnew()
|
func Test_listdict_extendnew()
|
||||||
|
@@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
2738,
|
||||||
/**/
|
/**/
|
||||||
2737,
|
2737,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user