mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-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.
dd29ea1805
This commit is contained in:
parent
e140eec441
commit
23f5999d28
@ -2599,15 +2599,16 @@ void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip)
|
||||
fi->fi_lw.lw_item = tv_list_first(l);
|
||||
}
|
||||
} else if (tv.v_type == VAR_BLOB) {
|
||||
blob_T *const b = tv.vval.v_blob;
|
||||
if (b == NULL) {
|
||||
tv_clear(&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.
|
||||
tv_blob_copy(&tv, &btv);
|
||||
fi->fi_blob = btv.vval.v_blob;
|
||||
}
|
||||
tv_clear(&tv);
|
||||
} else {
|
||||
EMSG(_(e_listreq));
|
||||
tv_clear(&tv);
|
||||
@ -9737,17 +9738,7 @@ int var_item_copy(const vimconv_T *const conv,
|
||||
}
|
||||
break;
|
||||
case VAR_BLOB:
|
||||
to->v_type = VAR_BLOB;
|
||||
if (from->vval.v_blob == NULL) {
|
||||
to->vval.v_blob = NULL;
|
||||
} else {
|
||||
tv_blob_alloc_ret(to);
|
||||
const int len = from->vval.v_blob->bv_ga.ga_len;
|
||||
|
||||
to->vval.v_blob->bv_ga.ga_data
|
||||
= xmemdup(from->vval.v_blob->bv_ga.ga_data, (size_t)len);
|
||||
to->vval.v_blob->bv_ga.ga_len = len;
|
||||
}
|
||||
tv_blob_copy(from, to);
|
||||
break;
|
||||
case VAR_DICT:
|
||||
to->v_type = VAR_DICT;
|
||||
|
@ -2252,6 +2252,30 @@ void tv_blob_alloc_ret(typval_T *const ret_tv)
|
||||
tv_blob_set_ret(ret_tv, b);
|
||||
}
|
||||
|
||||
/// Copy a blob typval to a different typval.
|
||||
///
|
||||
/// @param[in] from Blob object to copy from.
|
||||
/// @param[out] to Blob object to copy to.
|
||||
void tv_blob_copy(typval_T *const from, typval_T *const to)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
assert(from->v_type == VAR_BLOB);
|
||||
|
||||
to->v_type = VAR_BLOB;
|
||||
if (from->vval.v_blob == NULL) {
|
||||
to->vval.v_blob = NULL;
|
||||
} else {
|
||||
tv_blob_alloc_ret(to);
|
||||
const int len = from->vval.v_blob->bv_ga.ga_len;
|
||||
|
||||
if (len > 0) {
|
||||
to->vval.v_blob->bv_ga.ga_data
|
||||
= xmemdup(from->vval.v_blob->bv_ga.ga_data, (size_t)len);
|
||||
}
|
||||
to->vval.v_blob->bv_ga.ga_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
//{{{3 Clear
|
||||
#define TYPVAL_ENCODE_ALLOW_SPECIALS false
|
||||
|
||||
|
@ -154,6 +154,7 @@ func Test_blob_for_loop()
|
||||
call assert_equal(i, byte)
|
||||
let i += 1
|
||||
endfor
|
||||
call assert_equal(4, i)
|
||||
|
||||
let blob = 0z00
|
||||
call remove(blob, 0)
|
||||
@ -161,6 +162,19 @@ func Test_blob_for_loop()
|
||||
for byte in blob
|
||||
call assert_error('loop over empty blob')
|
||||
endfor
|
||||
|
||||
let blob = 0z0001020304
|
||||
let i = 0
|
||||
for byte in blob
|
||||
call assert_equal(i, byte)
|
||||
if i == 1
|
||||
call remove(blob, 0)
|
||||
elseif i == 3
|
||||
call remove(blob, 3)
|
||||
endif
|
||||
let i += 1
|
||||
endfor
|
||||
call assert_equal(5, i)
|
||||
endfunc
|
||||
|
||||
func Test_blob_concatenate()
|
||||
|
Loading…
Reference in New Issue
Block a user