comparison src/list.c @ 24396:d406858354a6 v8.2.2738

patch 8.2.2738: extending a list with itself can give wrong result Commit: https://github.com/vim/vim/commit/dcae51facc4d6de1edd62f0242b40972be841103 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Apr 8 20:10:10 2021 +0200 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)
author Bram Moolenaar <Bram@vim.org>
date Thu, 08 Apr 2021 20:15:03 +0200
parents e695db9a5465
children 5c6ccab68d1e
comparison
equal deleted inserted replaced
24395:5cd55703c76d 24396:d406858354a6
892 int 892 int
893 list_extend(list_T *l1, list_T *l2, listitem_T *bef) 893 list_extend(list_T *l1, list_T *l2, listitem_T *bef)
894 { 894 {
895 listitem_T *item; 895 listitem_T *item;
896 int todo; 896 int todo;
897 listitem_T *bef_prev;
897 898
898 // NULL list is equivalent to an empty list: nothing to do. 899 // NULL list is equivalent to an empty list: nothing to do.
899 if (l2 == NULL || l2->lv_len == 0) 900 if (l2 == NULL || l2->lv_len == 0)
900 return OK; 901 return OK;
901 902
902 todo = l2->lv_len; 903 todo = l2->lv_len;
903 CHECK_LIST_MATERIALIZE(l1); 904 CHECK_LIST_MATERIALIZE(l1);
904 CHECK_LIST_MATERIALIZE(l2); 905 CHECK_LIST_MATERIALIZE(l2);
905 906
907 // When exending a list with itself, at some point we run into the item
908 // that was before "bef" and need to skip over the already inserted items
909 // to "bef".
910 bef_prev = bef == NULL ? NULL : bef->li_prev;
911
906 // We also quit the loop when we have inserted the original item count of 912 // We also quit the loop when we have inserted the original item count of
907 // the list, avoid a hang when we extend a list with itself. 913 // the list, avoid a hang when we extend a list with itself.
908 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next) 914 for (item = l2->lv_first; item != NULL && --todo >= 0;
915 item = item == bef_prev ? bef : item->li_next)
909 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL) 916 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
910 return FAIL; 917 return FAIL;
911 return OK; 918 return OK;
912 } 919 }
913 920