buffer completion for large CJK document leads to segmentation fault of neovim
Make sure you have done the following
- [X] I have updated to the latest version of
blink.cmp - [X] I have read the README
Bug Description
I'm using LazyVim, which enables the buffer completion source for blink.cmp
https://github.com/LazyVim/LazyVim/blob/dc4345a5ee23ffb4aad50c01eca49d5bc47a96c3/lua/lazyvim/plugins/extras/coding/blink.lua#L76
when editing a large CJK document and modifying a long sentence in insert mode, neovim crashes with a segmentation fault right after the modification. I can no longer reproduce the crash once I disable buffer from completion sources, so I suspect there's something wrong with it
this is a random large Chinese document for reproducing the issue https://github.com/ArcturusZhang/Classical-Mechanics-Lecture-Notes/raw/refs/heads/master/chapter/chapter2.tex
below is the stack trace
#0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:76
No locals.
#1 0x0000650858389eea in xstrdup (str=0x0) at /usr/src/debug/neovim/neovim/src/nvim/memory.c:469
No locals.
#2 0x0000650858356744 in nlua_luv_thread_common_cfpcall (lstate=0x72535a3e0380, nargs=1, nresult=-1,
flags=1, is_callback=is_callback@entry=false) at /usr/src/debug/neovim/neovim/src/nvim/lua/executor.c:279
error = <optimized out>
retval = <optimized out>
top = 2
status = 2
#3 0x0000650858356895 in nlua_luv_thread_cfpcall (lstate=<optimized out>, nargs=<optimized out>,
nresult=<optimized out>, flags=<optimized out>)
at /usr/src/debug/neovim/neovim/src/nvim/lua/executor.c:244
No locals.
#4 0x0000725360b2b644 in luv_work_cb (L=0x72535a3e0380) at /usr/src/debug/libluv/luv-1.48.0-2/src/work.c:107
i = <optimized out>
req = <optimized out>
work = 0x6508705fac00
ctx = <optimized out>
lctx = 0x72535a3ea4d8
top = 0
#5 0x0000725360a17f06 in lj_BC_FUNCC () at buildvm_x86.dasc:857
No locals.
#6 0x0000725360a2c0aa in lua_pcall (L=L@entry=0x72535a3e0380, nargs=nargs@entry=1,
nresults=nresults@entry=0, errfunc=errfunc@entry=0)
at /usr/src/debug/luajit/LuaJIT-fe71d0fb54ceadfb5b5f3b6baf29e486d97f6059/src/lj_api.c:1122
g = 0x72535a3e03e0
oldh = 0 '\000'
ef = <optimized out>
status = <optimized out>
#7 0x00006508583566e7 in nlua_luv_thread_common_cfpcall (lstate=lstate@entry=0x72535a3e0380,
nargs=nargs@entry=1, nresult=nresult@entry=0, flags=flags@entry=1, is_callback=is_callback@entry=false)
at /usr/src/debug/neovim/neovim/src/nvim/lua/executor.c:263
retval = <optimized out>
top = 2
status = <optimized out>
#8 0x0000650858356895 in nlua_luv_thread_cfpcall (lstate=lstate@entry=0x72535a3e0380, nargs=nargs@entry=1,
nresult=nresult@entry=0, flags=flags@entry=1) at /usr/src/debug/neovim/neovim/src/nvim/lua/executor.c:244
No locals.
#9 0x00006508583568dd in nlua_luv_thread_cfcpcall (lstate=0x72535a3e0380, func=<optimized out>,
ud=0x6508705fac00, flags=1) at /usr/src/debug/neovim/neovim/src/nvim/lua/executor.c:252
retval = <optimized out>
#10 0x0000725360b2b8aa in luv_work_cb_wrapper (req=0x6508705fac00)
at /usr/src/debug/libluv/luv-1.48.0-2/src/work.c:155
work = 0x6508705fac00
L = 0x72535a3e0380
lctx = <optimized out>
i = <optimized out>
#11 0x000072536090030a in worker (arg=0x0) at src/threadpool.c:122
w = 0x6508705fac58
q = 0x6508705fac70
is_slow_work = 0
Relevant configuration
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
-- uncomment the following block avoids segmentation fault
-- {
-- "saghen/blink.cmp",
-- opts = {
-- sources = {
-- default = function()
-- return { "lsp", "path", "snippets" }
-- end,
-- },
-- },
-- },
},
})
neovim version
v0.10.2
blink.cmp version: branch, tag, or commit
v0.7.6
Do we really need this '+ 1'? It seems that removing this line solves the problem.
https://github.com/Saghen/blink.cmp/blob/217f670d85d8b56f48146636b61019ccd072f9cc/lua/blink/cmp/sources/buffer.lua#L21-L24
It also produces a (seemingly) weird chunk:
Typing ipsum on a text:
Lorem {cursor} dolor sit amet, consectetur adipiscing elit. Gravida mus sociosqu
with start_col = start_col + 1:
{
_line = "Lorem i dolor sit amet, consectetur adipiscing elit. Gravida mus sociosqu"
}
without start_col = start_col + 1:
{
_line = "Lorem dolor sit amet, consectetur adipiscing elit. Gravida mus sociosqu"
}
Typing bar baz on a text:
foo("{cursor}")
with start_col = start_col + 1:
{
_line = 'foo("b ")'
}
{
_line = 'foo("bar b ")'
}
without start_col = start_col + 1:
{
_line = 'foo(" ")'
}
{
_line = 'foo("bar ")'
}
Do we really need this '+ 1'? It seems that removing this line solves the problem.
confirmed
Thanks for debugging this @itepechi!