Mercurial > vim
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 |