Greetings,
My environment is Ubuntu 18.04, GNOME Terminal.
While tinkering around, I discovered that the following snippet of
Vimscript will result in a segfault:
" This produces a segfault.
while 1
silent! let v:errmsg = []
let v:errmsg = ''
endwhile
The loop is there because you may have to execute the sequence
a couple of times before a segfault happens.
Also notice that running:
:let v:errmsg = []
:echo v:errmsg
does not show the last generated error message as one would expect,
it shows the empty string.
I wrote a test to prove that my patch sets the error message in
this case:
func Test_let_errmsg()
silent! let v:errmsg = []
call assert_false(empty(v:errmsg))
endfunc
I'm not exactly sure where to put the test... there were several
test scripts that seemed relevant here.
I dug into the code and came up with this:
diff --git a/src/eval.c b/src/eval.c
index d1a7fd37d..c485ecabd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -7883,20 +7883,23 @@ set_var(
|| tv_check_lock(v->di_tv.v_lock, name, FALSE))
return;
- /*
- * Handle setting internal v: variables separately where needed to
- * prevent changing the type.
- */
+ // Handle setting internal v: variables separately where needed to
+ // prevent changing the type.
if (ht == &vimvarht)
{
if (v->di_tv.v_type == VAR_STRING)
{
- vim_free(v->di_tv.vval.v_string);
+ VIM_CLEAR(v->di_tv.vval.v_string);
if (copy || tv->v_type != VAR_STRING)
- v->di_tv.vval.v_string = vim_strsave(tv_get_string(tv));
+ {
+ if (STRCMP("v:errmsg", name) == 0)
+ tv_get_string(tv); // calls emsg(), which sets v:errmsg
+ else
+ v->di_tv.vval.v_string = vim_strsave(tv_get_string(tv));
+ }
else
{
- /* Take over the string to avoid an extra alloc/free. */
+ // Take over the string to avoid an extra alloc/free.
v->di_tv.vval.v_string = tv->vval.v_string;
tv->vval.v_string = NULL;
}
This patch stops the segfault from happening and lets the check of the "tv"
variable set v:errmsg (see comment).
I would appreciate some careful review here. I don't precisely understand
why VIM_CLEAR works instead of vim_free(). I suspect it is due to some check
for NULL later. Any feedback to help my understanding is always appreciated.
It may be that a much better solution exists, but I'm not really familiar
enough with the code to arrive at the perfect fix... though I try.
Best,
Jason Franklin
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.