mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(api): validate command names in nvim_add_user_command (#17406)
This uses the same validation used when defining commands with `:command`.
This commit is contained in:
parent
3449405f38
commit
238b944e58
@ -1384,6 +1384,11 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int
|
|||||||
LuaRef luaref = LUA_NOREF;
|
LuaRef luaref = LUA_NOREF;
|
||||||
LuaRef compl_luaref = LUA_NOREF;
|
LuaRef compl_luaref = LUA_NOREF;
|
||||||
|
|
||||||
|
if (!uc_validate_name(name.data)) {
|
||||||
|
api_set_error(err, kErrorTypeValidation, "Invalid command name");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (mb_islower(name.data[0])) {
|
if (mb_islower(name.data[0])) {
|
||||||
api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
|
api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -5164,6 +5164,24 @@ char_u *get_command_name(expand_T *xp, int idx)
|
|||||||
return cmdnames[idx].cmd_name;
|
return cmdnames[idx].cmd_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check for a valid user command name
|
||||||
|
///
|
||||||
|
/// If the given {name} is valid, then a pointer to the end of the valid name is returned.
|
||||||
|
/// Otherwise, returns NULL.
|
||||||
|
char *uc_validate_name(char *name)
|
||||||
|
{
|
||||||
|
if (ASCII_ISALPHA(*name)) {
|
||||||
|
while (ASCII_ISALNUM(*name)) {
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ends_excmd(*name) && !ascii_iswhite(*name)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, long def, int flags,
|
int uc_add_command(char_u *name, size_t name_len, char_u *rep, uint32_t argt, long def, int flags,
|
||||||
int compl, char_u *compl_arg, LuaRef compl_luaref, cmd_addr_T addr_type,
|
int compl, char_u *compl_arg, LuaRef compl_luaref, cmd_addr_T addr_type,
|
||||||
LuaRef luaref, bool force)
|
LuaRef luaref, bool force)
|
||||||
@ -5679,23 +5697,18 @@ static void ex_command(exarg_T *eap)
|
|||||||
|
|
||||||
// Get the name (if any) and skip to the following argument.
|
// Get the name (if any) and skip to the following argument.
|
||||||
name = p;
|
name = p;
|
||||||
if (ASCII_ISALPHA(*p)) {
|
end = (char_u *)uc_validate_name((char *)name);
|
||||||
while (ASCII_ISALNUM(*p)) {
|
if (!end) {
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ends_excmd(*p) && !ascii_iswhite(*p)) {
|
|
||||||
emsg(_("E182: Invalid command name"));
|
emsg(_("E182: Invalid command name"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
end = p;
|
name_len = (size_t)(end - name);
|
||||||
name_len = (int)(end - name);
|
|
||||||
|
|
||||||
// If there is nothing after the name, and no attributes were specified,
|
// If there is nothing after the name, and no attributes were specified,
|
||||||
// we are listing commands
|
// we are listing commands
|
||||||
p = skipwhite(end);
|
p = skipwhite(end);
|
||||||
if (!has_attr && ends_excmd(*p)) {
|
if (!has_attr && ends_excmd(*p)) {
|
||||||
uc_list(name, end - name);
|
uc_list(name, name_len);
|
||||||
} else if (!ASCII_ISUPPER(*name)) {
|
} else if (!ASCII_ISUPPER(*name)) {
|
||||||
emsg(_("E183: User defined commands must start with an uppercase letter"));
|
emsg(_("E183: User defined commands must start with an uppercase letter"));
|
||||||
} else if (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0) {
|
} else if (name_len <= 4 && STRNCMP(name, "Next", name_len) == 0) {
|
||||||
@ -5703,7 +5716,7 @@ static void ex_command(exarg_T *eap)
|
|||||||
} else if (compl > 0 && (argt & EX_EXTRA) == 0) {
|
} else if (compl > 0 && (argt & EX_EXTRA) == 0) {
|
||||||
emsg(_(e_complete_used_without_nargs));
|
emsg(_(e_complete_used_without_nargs));
|
||||||
} else {
|
} else {
|
||||||
uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, LUA_NOREF,
|
uc_add_command(name, name_len, p, argt, def, flags, compl, compl_arg, LUA_NOREF,
|
||||||
addr_type_arg, LUA_NOREF, eap->forceit);
|
addr_type_arg, LUA_NOREF, eap->forceit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,28 @@ describe('nvim_add_user_command', function()
|
|||||||
feed('<C-U>Test b<Tab>')
|
feed('<C-U>Test b<Tab>')
|
||||||
eq('Test bbb', funcs.getcmdline())
|
eq('Test bbb', funcs.getcmdline())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('does not allow invalid command names', function()
|
||||||
|
matches("'name' must begin with an uppercase letter", pcall_err(exec_lua, [[
|
||||||
|
vim.api.nvim_add_user_command('test', 'echo "hi"', {})
|
||||||
|
]]))
|
||||||
|
|
||||||
|
matches('Invalid command name', pcall_err(exec_lua, [[
|
||||||
|
vim.api.nvim_add_user_command('t@', 'echo "hi"', {})
|
||||||
|
]]))
|
||||||
|
|
||||||
|
matches('Invalid command name', pcall_err(exec_lua, [[
|
||||||
|
vim.api.nvim_add_user_command('T@st', 'echo "hi"', {})
|
||||||
|
]]))
|
||||||
|
|
||||||
|
matches('Invalid command name', pcall_err(exec_lua, [[
|
||||||
|
vim.api.nvim_add_user_command('Test!', 'echo "hi"', {})
|
||||||
|
]]))
|
||||||
|
|
||||||
|
matches('Invalid command name', pcall_err(exec_lua, [[
|
||||||
|
vim.api.nvim_add_user_command('💩', 'echo "hi"', {})
|
||||||
|
]]))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('nvim_del_user_command', function()
|
describe('nvim_del_user_command', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user