match(), matchstr(), matchend(), matchlist() and matchstrpos()
over a list, join() of a list, and string() or :echo of a list or
dict stringify each item while iterating over the container. When an item
is an object this runs its user-defined string() method, which can remove
the item the loop is standing on, or grow a dict so that its hash table is
reallocated. Either leaves the loop reading freed memory.
find_some_match() in evalfunc.c, list_join_inner() in list.c and
dict2string() in dict.c each iterate a container while calling
echo_string(). A minimal reproducer for each crashes an unpatched Vim:
vim9script class C def string(): string if len(g:l) > 0 remove(g:l, 0) endif return 'x' enddef endclass g:l = [C.new(), C.new(), C.new()] echo match(g:l, 'y') " also: join(g:l), string(g:l)
Lock the container while iterating, so a change from the string() method
fails with E741 instead of corrupting the iterator, the same way
filter(), map(), sort() and reduce() already do. For a dict also
hash_lock() it, so a grow cannot reallocate the hash table mid-iteration,
mirroring the dict path of filter()/map(). list_reduce() was the
existing pattern these three were missing.
Adds tests for match() and matchstr() over a list, join() and
string() of a list, and string() of a dict, each with an object whose
string() method mutates the container; every one crashes an unpatched
Vim.
AI assistance is acknowledged with Co-Authored-By trailers on the commit,
per AGENTS.md.
https://github.com/vim/vim/pull/21001
(4 files)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()