diff src/eval.c @ 15581:c2382f0d1279 v8.1.0798

patch 8.1.0798: changing a blob while iterating over it works strangely commit https://github.com/vim/vim/commit/dd29ea18050284526174b5685781469240f5bc4a Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jan 23 21:56:21 2019 +0100 patch 8.1.0798: changing a blob while iterating over it works strangely Problem: Changing a blob while iterating over it works strangely. Solution: Make a copy of the Blob before iterating.
author Bram Moolenaar <Bram@vim.org>
date Wed, 23 Jan 2019 22:00:06 +0100
parents dd725a8ab112
children 44ea60ca593b
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -2587,7 +2587,6 @@ eval_for_line(
     char_u	*expr;
     typval_T	tv;
     list_T	*l;
-    blob_T	*b;
 
     *errp = TRUE;	/* default: there is an error */
 
@@ -2632,16 +2631,17 @@ eval_for_line(
 	    }
 	    else if (tv.v_type == VAR_BLOB)
 	    {
-		b = tv.vval.v_blob;
-		if (b == NULL)
-		    clear_tv(&tv);
-		else
-		{
-		    // No need to increment the refcount, it's already set for
-		    // the blob being used in "tv".
-		    fi->fi_blob = b;
-		    fi->fi_bi = 0;
-		}
+		fi->fi_bi = 0;
+		if (tv.vval.v_blob != NULL)
+		{
+		    typval_T btv;
+
+		    // Make a copy, so that the iteration still works when the
+		    // blob is changed.
+		    blob_copy(&tv, &btv);
+		    fi->fi_blob = btv.vval.v_blob;
+		}
+		clear_tv(&tv);
 	    }
 	    else
 	    {
@@ -8076,7 +8076,7 @@ tv_check_lock(int lock, char_u *name, in
 /*
  * Copy the values from typval_T "from" to typval_T "to".
  * When needed allocates string or increases reference count.
- * Does not make a copy of a list or dict but copies the reference!
+ * Does not make a copy of a list, blob or dict but copies the reference!
  * It is OK for "from" and "to" to point to the same item.  This is used to
  * make a copy later.
  */
@@ -8216,19 +8216,7 @@ item_copy(
 		ret = FAIL;
 	    break;
 	case VAR_BLOB:
-	    to->v_type = VAR_BLOB;
-	    if (from->vval.v_blob == NULL)
-		to->vval.v_blob = NULL;
-	    else if (rettv_blob_alloc(to) == FAIL)
-		ret = FAIL;
-	    else
-	    {
-		int  len = from->vval.v_blob->bv_ga.ga_len;
-
-		to->vval.v_blob->bv_ga.ga_data =
-			    vim_memsave(from->vval.v_blob->bv_ga.ga_data, len);
-		to->vval.v_blob->bv_ga.ga_len = len;
-	    }
+	    ret = blob_copy(from, to);
 	    break;
 	case VAR_DICT:
 	    to->v_type = VAR_DICT;