[vim/vim] Vim script can overwrite builtin function (#8302)

78 views
Skip to first unread message

mattn

unread,
May 31, 2021, 11:50:52 AM5/31/21
to vim/vim, Subscribed

let g:.foo = 1 let 1 to global variable foo. And this way can overwrite builtin functions.

Describe the bug

let g:.foo = 1 let 1 to global variable foo. And this way can overwrite builtin functions.

To Reproduce

let g:.trim = {x-> ' '..x..' '}
echo '['..trim(' foo ')..']'

This get [ foo ].

Expected behavior

[foo]


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

mattn

unread,
May 31, 2021, 12:00:37 PM5/31/21
to vim/vim, Subscribed

This is also wrong.

let g:['trim'] = {x-> ' '..x..' '}
echo '['..trim(' foo ')..']'

mattn

unread,
May 31, 2021, 12:49:08 PM5/31/21
to vim/vim, Subscribed

This should fix the issue.

diff --git a/src/userfunc.c b/src/userfunc.c
index f5d906302..e463d73cd 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1436,6 +1436,12 @@ deref_func_name(
 
     cc = name[*lenp];
     name[*lenp] = NUL;
+
+    if (builtin_function(name, -1)) {
+	name[*lenp] = cc;
+	return name;
+    }
+
     v = find_var(name, &ht, no_autoload);
     name[*lenp] = cc;
     if (v != NULL)

Bram Moolenaar

unread,
May 31, 2021, 4:05:19 PM5/31/21
to vim/vim, Subscribed

Besides that check, it should not even be possible to add that variable in g: or s:

Bram Moolenaar

unread,
May 31, 2021, 4:16:05 PM5/31/21
to vim/vim, Subscribed

Closed #8302 via 3d9c4ee.

Bram Moolenaar

unread,
May 31, 2021, 4:16:51 PM5/31/21
to vim/vim, Subscribed

Actually, we cannot use builtin_function(), because in lambda's using a lower case name is possible.

mattn

unread,
May 31, 2021, 7:43:57 PM5/31/21
to vim/vim, Subscribed

@brammool Thank you. But still wrong.

call extend(g:, #{foo: { -> 'foo' }})

mattn

unread,
May 31, 2021, 8:24:56 PM5/31/21
to vim/vim, Subscribed

@brammool another degrade with this fix.

let s:trim = {x-> ' '..x..' '}

This makes error E704.

mattn

unread,
May 31, 2021, 8:34:39 PM5/31/21
to vim/vim, Subscribed

I prefer checking for the referencing to the symbol, Not checking for letting variables.

Bram Moolenaar

unread,
Jun 1, 2021, 3:31:26 PM6/1/21
to vim/vim, Subscribed


> @brammool another degrade with this fix.
>
> ```
> let s:trim = {x-> ' '..x..' '}
> ```
> This makes error E704.

That looks correct, it should use "s:Trim".

Did this work OK before? Then we might have to check this only in Vim9
script, where script-local variables can be used without s: prefix.

Actually, I cannot reproduce the error in legacy script. And I do get
the error in Vim 9 script, looks OK to me. Did you have some context to
trigger the error?

--
ARTHUR: No, hang on! Just answer the five questions ...
GALAHAD: Three questions ...
ARTHUR: Three questions ... And we shall watch ... and pray.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

mattn

unread,
Jun 2, 2021, 2:34:29 AM6/2/21
to vim/vim, Subscribed

:let s:.foo = { -> 'foo' }
:echo s:foo()

Vim(let):E704: Funcref variable name must start with a capital: foo

mattn

unread,
Jun 2, 2021, 2:49:58 AM6/2/21
to vim/vim, Subscribed

:let g:s = s:
function! CallS(name)
  return s:[a:name]()
endfunction
:let g:s.foo = { -> 'foo' }
:echo CallS('foo')

K.Takata

unread,
Jun 2, 2021, 3:25:41 AM6/2/21
to vim/vim, Subscribed

:help E704 says:

<							*E704* *E705* *E707*
A Funcref variable must start with a capital, "s:", "w:", "t:" or "b:".  You
can use "g:" but the following name must still start with a capital.  You
cannot have both a Funcref variable and a function with the same name.

so, I think "s:" should be able to be followed by a lower letter.

And, I think that "s:" in this part should be changed to "l:"
3d9c4ee#diff-3452ba3ede8c12266b78c613c3171f5a19f42244731749b3bc60072cdf45be46R2687-R2688
as follows:

  call assert_fails('let l:["trim"] = {x -> " " .. x}', 'E704:')
  call assert_fails('let l:.trim = {x -> " " .. x}', 'E704:')

Bram Moolenaar

unread,
Jun 2, 2021, 5:51:03 AM6/2/21
to vim/vim, Subscribed


> ```

> :let s:.foo = { -> 'foo' }
> :echo s:foo()
> ```
> >Vim(let):E704: Funcref variable name must start with a capital: foo

Looks like I missed the dot.

--
BRIDGEKEEPER: What is your favorite colour?
GAWAIN: Blue ... No yelloooooww!

"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Bram Moolenaar

unread,
Jun 2, 2021, 5:51:04 AM6/2/21
to vim/vim, Subscribed


> `:help E704` says:
> ```
> < *E704* *E705* *E707*
> A Funcref variable must start with a capital, "s:", "w:", "t:" or "b:". You
> can use "g:" but the following name must still start with a capital. You
> cannot have both a Funcref variable and a function with the same name.
> ```
> so, I think "s:" should be able to be followed by a lower letter.

In legacy script, yes. But in Vim9 script a script-local variable can
be accessed without s:, so there we won't allow it.

But in Vim9 script assigning to s:.trim won't work, it tries to parse
".trim" as a type. Same for s:['trim'].



> And, I think that "s:" in this part should be changed to "l:"
> https://github.com/vim/vim/commit/3d9c4eefe656ee8bf58c0496a48bd56bac180056#diff-3452ba3ede8c12266b78c613c3171f5a19f42244731749b3bc60072cdf45be46R2687-R2688
> as follows:
> ```vim

> call assert_fails('let l:["trim"] = {x -> " " .. x}', 'E704:')
> call assert_fails('let l:.trim = {x -> " " .. x}', 'E704:')
> ```

Except that this doesn't fail yet.


--
BRIDGEKEEPER: What is your favorite colour?
LAUNCELOT: Blue.
BRIDGEKEEPER: Right. Off you go.

"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Bram Moolenaar

unread,
Jun 2, 2021, 7:52:52 AM6/2/21
to vim/vim, Subscribed


> ```

> :let g:s = s:
> function! CallS(name)
> return s:[a:name]()
> endfunction
> :let g:s.foo = { -> 'foo' }
> :echo CallS('foo')
> ```

After the recent changes this also works correctly. For legacy script
this is allowed, s:foo can be a function. For Vim9 script it gives the
E704 error.

--
BEDEVERE: How do you know so much about swallows?
ARTHUR: Well you have to know these things when you're a king, you know.

"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Reply all
Reply to author
Forward
0 new messages