]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.1210: using ht_used when looping through a hashtab is less reliable v8.2.1210
authorBram Moolenaar <Bram@vim.org>
Tue, 14 Jul 2020 19:08:49 +0000 (21:08 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 14 Jul 2020 19:08:49 +0000 (21:08 +0200)
Problem:    Using ht_used when looping through a hashtab is less reliable.
Solution:   Use ht_changed in a few more places.

src/if_py_both.h
src/userfunc.c
src/version.c

index 5bd6a0e67728a0d6b50402b7733298df980a3549..8eb77470a3d6b959986197ae1305f4c59fe541e1 100644 (file)
@@ -1792,11 +1792,10 @@ DictionaryContains(DictionaryObject *self, PyObject *keyObject)
 
 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);
+    while (((*dii)->dii_todo) && HASHITEM_EMPTY((*dii)->dii_hi))
+       ++((*dii)->dii_hi);
 
-    --((*dii)->todo);
+    --((*dii)->dii_todo);
 
-    if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
+    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,
index 6e49c035cff40327c9a5226d5c1e5ee766338f41..b4b8ccf9106c2ec8114432bdbb5002913e20254e 100644 (file)
@@ -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 check)
 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;
index f49eec9738b5a8697bb9a134193f54feb0f6be05..6be113dcac77b2b177a3ced16dfa26c3200be0a7 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1210,
 /**/
     1209,
 /**/