changeset 21319:fb3dcd8ed14d v8.2.1210

patch 8.2.1210: using ht_used when looping through a hashtab is less reliable Commit: https://github.com/vim/vim/commit/1f22cc5cdb2da867d6bbf54dd371f279c38a2f56 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Jul 14 21:08:49 2020 +0200 patch 8.2.1210: using ht_used when looping through a hashtab is less reliable Problem: Using ht_used when looping through a hashtab is less reliable. Solution: Use ht_changed in a few more places.
author Bram Moolenaar <Bram@vim.org>
date Tue, 14 Jul 2020 21:15:04 +0200
parents b1121f5c029a
children 438b5a226cc7
files src/if_py_both.h src/userfunc.c src/version.c
diffstat 3 files changed, 28 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -1792,11 +1792,10 @@ DictionaryContains(DictionaryObject *sel
 
 typedef struct
 {
-    hashitem_T	*ht_array;
-    long_u	ht_used;
-    hashtab_T	*ht;
-    hashitem_T	*hi;
-    long_u	todo;
+    int		dii_changed;
+    hashtab_T	*dii_ht;
+    hashitem_T	*dii_hi;
+    long_u	dii_todo;
 } dictiterinfo_T;
 
     static PyObject *
@@ -1804,23 +1803,22 @@ DictionaryIterNext(dictiterinfo_T **dii)
 {
     PyObject	*ret;
 
-    if (!(*dii)->todo)
+    if (!(*dii)->dii_todo)
 	return NULL;
 
-    if ((*dii)->ht->ht_array != (*dii)->ht_array ||
-	    (*dii)->ht->ht_used != (*dii)->ht_used)
+    if ((*dii)->dii_ht->ht_changed != (*dii)->dii_changed)
     {
 	PyErr_SET_STRING(PyExc_RuntimeError,
 		N_("hashtab changed during iteration"));
 	return NULL;
     }
 
-    while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
-	++((*dii)->hi);
-
-    --((*dii)->todo);
-
-    if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
+    while (((*dii)->dii_todo) && HASHITEM_EMPTY((*dii)->dii_hi))
+	++((*dii)->dii_hi);
+
+    --((*dii)->dii_todo);
+
+    if (!(ret = PyBytes_FromString((char *)(*dii)->dii_hi->hi_key)))
 	return NULL;
 
     return ret;
@@ -1839,11 +1837,10 @@ DictionaryIter(DictionaryObject *self)
     }
 
     ht = &self->dict->dv_hashtab;
-    dii->ht_array = ht->ht_array;
-    dii->ht_used = ht->ht_used;
-    dii->ht = ht;
-    dii->hi = dii->ht_array;
-    dii->todo = dii->ht_used;
+    dii->dii_changed = ht->ht_changed;
+    dii->dii_ht = ht;
+    dii->dii_hi = ht->ht_array;
+    dii->dii_todo = ht->ht_used;
 
     return IterNew(dii,
 	    (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1712,7 +1712,7 @@ free_all_functions(void)
     ufunc_T	*fp;
     long_u	skipped = 0;
     long_u	todo = 1;
-    long_u	used;
+    int		changed;
 
     // Clean up the current_funccal chain and the funccal stack.
     while (current_funccal != NULL)
@@ -1743,9 +1743,9 @@ free_all_functions(void)
 		    ++skipped;
 		else
 		{
-		    used = func_hashtab.ht_used;
+		    changed = func_hashtab.ht_changed;
 		    func_clear(fp, TRUE);
-		    if (used != func_hashtab.ht_used)
+		    if (changed != func_hashtab.ht_changed)
 		    {
 			skipped = 0;
 			break;
@@ -2484,12 +2484,11 @@ untrans_function_name(char_u *name)
     static void
 list_functions(regmatch_T *regmatch)
 {
-    long_u	used = func_hashtab.ht_used;
-    long_u	todo = used;
-    hashitem_T	*ht_array = func_hashtab.ht_array;
+    int		changed = func_hashtab.ht_changed;
+    long_u	todo = func_hashtab.ht_used;
     hashitem_T	*hi;
 
-    for (hi = ht_array; todo > 0 && !got_int; ++hi)
+    for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
     {
 	if (!HASHITEM_EMPTY(hi))
 	{
@@ -2504,8 +2503,7 @@ list_functions(regmatch_T *regmatch)
 			    && vim_regexec(regmatch, fp->uf_name, 0)))
 	    {
 		list_func_head(fp, FALSE);
-		if (used != func_hashtab.ht_used
-			|| ht_array != func_hashtab.ht_array)
+		if (changed != func_hashtab.ht_changed)
 		{
 		    emsg(_("E454: function list was modified"));
 		    return;
@@ -3564,6 +3562,7 @@ get_expanded_name(char_u *name, int chec
 get_user_func_name(expand_T *xp, int idx)
 {
     static long_u	done;
+    static int		changed;
     static hashitem_T	*hi;
     ufunc_T		*fp;
 
@@ -3571,8 +3570,9 @@ get_user_func_name(expand_T *xp, int idx
     {
 	done = 0;
 	hi = func_hashtab.ht_array;
+	changed = func_hashtab.ht_changed;
     }
-    if (done < func_hashtab.ht_used)
+    if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used)
     {
 	if (done++ > 0)
 	    ++hi;
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1210,
+/**/
     1209,
 /**/
     1208,