-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
latest update to nvim-cmp causes stack overflow crash #12
Comments
I can't replicate it. |
I have this in my # Disable completion from the language server
options(languageserver.server_capabilities =
list(completionProvider = FALSE,
completionItemResolve = FALSE)) |
I have the same. I will investigate. |
I have found that the overflow occurs in ---Copy table
---@generic T
---@param tbl T
---@return T
misc.copy = function(tbl)
if type(tbl) ~= 'table' then
return tbl
end
if islist(tbl) then
local copy = {}
for i, value in ipairs(tbl) do
copy[i] = misc.copy(value)
end
return copy
end
local copy = {}
for key, value in pairs(tbl) do
copy[key] = misc.copy(value)
end
return copy
end This loops infinitely with this table:
I am not sure what is going on. All other lsp (python, etc.) still work fine. |
More investigation. At some point nvim-cmp receive this from cmp_r
|
I found the problematic commit: using this fixes the issue for now "hrsh7th/nvim-cmp",
commit = "ae644feb7b67bf1ce4260c231d1d4300b19c6f30", |
for k, v in pairs(completion_item) do
self.completion_item[k] = v or self.completion_item[k]
end I have no familiarity with Anyway, I can't replicate the bug on my side. |
I fixed two bugs in the C code in the last commit. After starting R and opening the Object Browser, the bugs could be replicated with the following code: ddd <- data.frame(aa = 1, bb = 2)
rm(ddd)
x <- 1 Bug 1: The Object Browser wasn't updated after Bug 2: Invalid string received by Maybe the second bug was causing the stack overflow crash in |
ah nice, i am actively trying to debug this for the past hour. Have you created a branch? |
No luck, still having this when I hit enter on a completion selection
I am trying to make a reproducible example with this https://github.com/hrsh7th/nvim-cmp/blob/main/utils/vimrc.vim |
I am able to reproduce with this if has('vim_starting')
set encoding=utf-8
endif
scriptencoding utf-8
if &compatible
set nocompatible
endif
let s:plug_dir = expand('/tmp/plugged/vim-plug')
if !filereadable(s:plug_dir .. '/plug.vim')
execute printf('!curl -fLo %s/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim', s:plug_dir)
endif
execute 'set runtimepath+=' . s:plug_dir
call plug#begin(s:plug_dir)
" Plugin list
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
Plug 'R-nvim/cmp-r'
Plug 'R-nvim/R.nvim'
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
call plug#end()
PlugInstall | quit
" Setup nvim-cmp
lua << EOF
local cmp = require("cmp")
cmp.setup {
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<C-n>"] = cmp.mapping.select_next_item(),
["<C-p>"] = cmp.mapping.select_prev_item(),
["<C-d>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete({}),
["<CR>"] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.insert,
select = false,
}),
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
-- elseif luasnip.expand_or_locally_jumpable() then
-- luasnip.expand_or_jump()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
-- elseif luasnip.locally_jumpable(-1) then
-- luasnip.jump(-1)
else
fallback()
end
end, { "i", "s" }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "buffer" },
{ name = "cmp_r" },
})
}
-- Configure cmp-r
require("cmp_r").setup({})
-- require("R.nvim").setup({})
-- Set up LSP with cmp capabilities
local capabilities = require('cmp_nvim_lsp').default_capabilities()
EOF
" Setup Treesitter
lua << EOF
require'nvim-treesitter.configs'.setup {
ensure_installed = { "markdown", "markdown_inline", "r", "rnoweb", "yaml", "vim"},
highlight = {
enable = true, -- Enable syntax highlighting
},
}
EOF
Then open a file like this
|
Still no bug on my side with your
|
No luck either. With my minimal example, do you get any completion at all? And no crash? |
Yes, the completion works normally, and there is no crash. |
Very strange. This is starting nvim with nothing else. Maybe my nvim version? I will explore this. |
I tried both stable and nightly and same issue. |
A similar bug was already reported, but not reproducible hrsh7th/nvim-cmp#1347 |
I am updating lua, just in case, I am out of ideas. |
As far as I know, bugs such "stack overflow" or "buffer overflow" should only happen in languages with low-level access to memory management, such as C or C++. Other programming languages (Java, R, Python, Lua, etc...) protect their users from these bugs (they don't give users the power to create them). Can you replicate the bug on a different machine? |
Yes. Both on at home and at job. Both on linux. |
Makes sense. The issue is that the table received here #12 (comment) seems to contain indefinite number of entries and the copy function eventually crashes. |
More info. The error originate from the call to local completion_item = misc.copy(e.completion_item) If I add a print statement print("confirm", vim.inspect(e.completion_item))
local completion_item = misc.copy(e.completion_item) I am getting this output (when I select {
cls = "(",
documentation = {
kind = "markdown",
value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate o
nes. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `aov
` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method =
"qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n offset, ...)\n```\n'
},
env = "stats",
items = { <table 1> },
kind = 3,
label = "lm",
sortText = "9",
textEdit = {
newText = "lm",
range = {
["end"] = {
character = 1,
line = 0
},
start = {
character = 0,
line = 0
}
}
}
} This seems ok, the received table is only of length 1. misc.copy = function(tbl)
if type(tbl) ~= "table" then
return tbl
end
if islist(tbl) then
local copy = {}
-- print the length of the table
print("Reveived table in misc.copy\n" .. vim.inspect(tbl))
for i, value in ipairs(tbl) do
copy[i] = misc.copy(value)
end
return copy
end
local copy = {}
for key, value in pairs(tbl) do
copy[key] = misc.copy(value)
end
return copy
end If I print the content of the reveived Reveived table in misc.copy
<1>{ {
cls = "(",
documentation = {
kind = "markdown",
value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate
ones. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `a
ov` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method
= "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n offset, ...)\n```\n'
},
env = "stats",
items = <table 1>,
kind = 3,
label = "lm",
sortText = "9",
textEdit = {
newText = "lm",
range = {
["end"] = {
character = 2,
line = 0
},
start = {
character = 0,
line = 0
}
}
}
} }
Reveived table in misc.copy
<1>{ {
cls = "(",
documentation = {
kind = "markdown",
value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate
ones. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `a
ov` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method
= "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n offset, ...)\n```\n'
},
env = "stats",
items = <table 1>,
kind = 3,
label = "lm",
sortText = "9",
textEdit = {
newText = "lm",
range = {
["end"] = {
character = 2,
line = 0
},
start = {
character = 0,
line = 0
....
...
... |
I can't imagine the infinite loop coming from the sorting = {
comparators = {
cmp.config.compare.order,
},
}, |
I replaced my config with yours and still the same (but now the order is different). Added 2 print statements here and I never receive the "Done copy" message. feedkeys.call("", "n", function()
local ctx = context.new()
print("confirm", vim.inspect(e.completion_item))
local completion_item = misc.copy(e.completion_item)
print("Done copy")
if not completion_item.textEdit then
completion_item.textEdit = {}
local insertText = completion_item.insertText
if misc.empty(insertText) then
insertText = nil
end
completion_item.textEdit.newText = insertText or completion_item.word or completion_item.label
end
local behavior = option.behavior or config.get().confirmation.default_behavior
if behavior == types.cmp.ConfirmBehavior.Replace then
completion_item.textEdit.range = e.replace_range
else
completion_item.textEdit.range = e.insert_range
end
local diff_before = math.max(0, e.context.cursor.col - (completion_item.textEdit.range.start.character + 1))
local diff_after = math.max(0, (completion_item.textEdit.range["end"].character + 1) - e.context.cursor.col)
local new_text = completion_item.textEdit.newText
completion_item.textEdit.range.start.line = ctx.cursor.line
completion_item.textEdit.range.start.character = (ctx.cursor.col - 1) - diff_before
completion_item.textEdit.range["end"].line = ctx.cursor.line
completion_item.textEdit.range["end"].character = (ctx.cursor.col - 1) + diff_after
if api.is_insert_mode() then
if false then
--To use complex expansion debug.
vim.print({ -- luacheck: ignore
item = e.completion_item,
diff_before = diff_before,
diff_after = diff_after,
new_text = new_text,
text_edit_new_text = completion_item.textEdit.newText,
range_start = completion_item.textEdit.range.start.character,
range_end = completion_item.textEdit.range["end"].character,
original_range_start = e.completion_item.textEdit.range.start.character,
original_range_end = e.completion_item.textEdit.range["end"].character,
cursor_line = ctx.cursor_line,
cursor_col0 = ctx.cursor.col - 1,
})
end
local is_snippet = completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet
if is_snippet then
completion_item.textEdit.newText = ""
end
vim.lsp.util.apply_text_edits({ completion_item.textEdit }, ctx.bufnr, "utf-8")
local texts = vim.split(completion_item.textEdit.newText, "\n")
vim.api.nvim_win_set_cursor(0, {
completion_item.textEdit.range.start.line + #texts,
(#texts == 1 and (completion_item.textEdit.range.start.character + #texts[1]) or #texts[#texts]),
})
if is_snippet then
config.get().snippet.expand({
body = new_text,
insert_text_mode = completion_item.insertTextMode,
})
end
else
local keys = {}
table.insert(
keys,
keymap.backspace(
ctx.cursor_line:sub(completion_item.textEdit.range.start.character + 1, ctx.cursor.col - 1)
)
)
table.insert(
keys,
keymap.delete(ctx.cursor_line:sub(ctx.cursor.col, completion_item.textEdit.range["end"].character))
)
table.insert(keys, new_text)
feedkeys.call(table.concat(keys, ""), "in")
end
end) Ccing @yioneko and @hrsh7th just in case they have some ideas. |
Maybe this was caused by the bug fixed in the last R.nvim commit... |
No luck. Maybe I can close this if it is only me with this issue. |
I have added that to my init.lua vim.cmd("set verbosefile=~/.config/nvim/nvimlog")
vim.cmd("set verbose=3") I am getting this information on crash:
|
We can't the issue before it's fixed. |
Not yet. I made my own for eventually open an issue on |
@PMassicotte you are not alone. I have the same bug and I use your workaround for now. |
You can try making these changes: diff --git a/lua/cmp_r/init.lua b/lua/cmp_r/init.lua
index 9670b90..8b8a770 100644
--- a/lua/cmp_r/init.lua
+++ b/lua/cmp_r/init.lua
@@ -531,6 +531,7 @@ end
---the data to rnvimserver which calls back this function.
---@param txt string The text almost ready to be displayed.
source.resolve_cb = function(txt)
+ vim.fn.writefile({ "", vim.inspect(txt) }, "/tmp/cmp_r_resolve_log", "a")
local s = fix_doc(txt)
if last_compl_item.def then
s = last_compl_item.label .. fix_doc(last_compl_item.def) .. "\n---\n" .. s
@@ -546,6 +547,7 @@ end
---@param compl table The completion data.
source.complete_cb = function(cid, compl)
if cid ~= compl_id then return nil end
+ vim.fn.writefile({ "", vim.inspect(compl) }, "/tmp/cmp_r_complete_log", "a")
local resp = {}
for _, v in pairs(compl) do Then, look at the log files and try to find something strange. To follow the log files as more lines are appended: tail -f /tmp/cmp_r_resolve_log |
When I try to complete with selecting |
After replacing {
{ cls = "(", env = "nvimcom", label = "etags2ctags" },
{ cls = "(", env = "nvimcom", label = "nvim.interlace.rmd" },
{ cls = "(", env = "nvimcom", label = "nvim.interlace.rnoweb" },
--- 2552 lines omitted
{ cls = "(", env = "base", label = "xtfrm.POSIXlt" },
{ cls = "(", env = "base", label = "xzfile" },
{ cls = "(", env = "base", label = "zapsmall" }
} No visible problem. After replacing function stats::lm
**Fitting Linear Models**
`lm` is used to fit linear models, including multivariate ones. It can be used to carry out regression, single stratum analysis of variance and
analysis of covariance (although `aov` may provide a more convenient interface for these).
---
```r
lm(formula, data, subset, weights, na.action, method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,
offset, ...)
``` It's just a valid Markdown text. The |
In the Lua table from
My guess is that In the past, BSD users have fixed bugs in the C code of But if repeated labels were the problem, there should be no stack overflow when completing Conclusion: "I know that I know nothing". |
That seems to be a not so easy issue to fix. Thank you for looking at it. I will continue to investigate and report back if I find a solution. |
IMO, this issue should be fixed with this. |
Thanks you @hrsh7th. The last commit solved the issue. |
Thank you very much @hrsh7th , this solved it. Thank for the great plugin. |
I am getting a stack overflow when I am trying to use completion since the latest update of nvim-cmp (https://github.com/hrsh7th/nvim-cmp/commits/main/).
I am not sure how to debug that. Any ideas?
The text was updated successfully, but these errors were encountered: