fix(api): fix nvim_cmd crash with filename expansion (#20397)

This commit is contained in:
zeertzjq
2022-09-29 16:04:14 +08:00
committed by GitHub
parent 1cf44d6f57
commit 45707c1eae
3 changed files with 21 additions and 9 deletions

View File

@@ -830,13 +830,12 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
// Replace, :make and :grep with 'makeprg' and 'grepprg'. // Replace, :make and :grep with 'makeprg' and 'grepprg'.
char *p = replace_makeprg(eap, eap->arg, cmdlinep); char *p = replace_makeprg(eap, eap->arg, cmdlinep);
if (p != eap->arg) { if (p != eap->arg) {
// If replace_makeprg modified the cmdline string, correct the argument pointers. // If replace_makeprg() modified the cmdline string, correct the eap->arg pointer.
eap->arg = p; eap->arg = p;
// We can only know the position of the first argument because the argument list can be used // This cannot be a user command, so eap->args will not be used.
// multiple times in makeprg / grepprg. XFREE_CLEAR(eap->args);
if (argc >= 1) { XFREE_CLEAR(eap->arglens);
eap->args[0] = p; eap->argc = 0;
}
} }
} }

View File

@@ -3887,7 +3887,7 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch
} else { } else {
// Otherwise, argument gets shifted alongside the replaced text. // Otherwise, argument gets shifted alongside the replaced text.
// The amount of the shift is equal to the difference of the old and new string length. // The amount of the shift is equal to the difference of the old and new string length.
eap->args[j] = new_cmdline + (eap->args[j] - *cmdlinep) + (len - srclen); eap->args[j] = new_cmdline + ((eap->args[j] - *cmdlinep) + (ptrdiff_t)(len - srclen));
} }
} }

View File

@@ -14,6 +14,7 @@ local funcs = helpers.funcs
local iswin = helpers.iswin local iswin = helpers.iswin
local meths = helpers.meths local meths = helpers.meths
local matches = helpers.matches local matches = helpers.matches
local pesc = helpers.pesc
local mkdir_p = helpers.mkdir_p local mkdir_p = helpers.mkdir_p
local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
local is_os = helpers.is_os local is_os = helpers.is_os
@@ -3912,11 +3913,23 @@ describe('API', function()
eq({'aa'}, meths.buf_get_lines(0, 0, 1, false)) eq({'aa'}, meths.buf_get_lines(0, 0, 1, false))
assert_alive() assert_alive()
end) end)
it('supports filename expansion', function()
meths.cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {})
local arg = funcs.expand('%:p:h:t')
eq({ arg, arg }, funcs.argv())
end)
it("'make' command works when argument count isn't 1 #19696", function() it("'make' command works when argument count isn't 1 #19696", function()
command('set makeprg=echo') command('set makeprg=echo')
meths.cmd({ cmd = 'make' }, {}) command('set shellquote=')
matches('^:!echo ',
meths.cmd({ cmd = 'make' }, { output = true }))
assert_alive() assert_alive()
meths.cmd({ cmd = 'make', args = { 'foo', 'bar' } }, {}) matches('^:!echo foo bar',
meths.cmd({ cmd = 'make', args = { 'foo', 'bar' } }, { output = true }))
assert_alive()
local arg_pesc = pesc(funcs.expand('%:p:h:t'))
matches(('^:!echo %s %s'):format(arg_pesc, arg_pesc),
meths.cmd({ cmd = 'make', args = { '%:p:h:t', '%:p:h:t' } }, { output = true }))
assert_alive() assert_alive()
end) end)
it('doesn\'t display messages when output=true', function() it('doesn\'t display messages when output=true', function()