diff options
-rw-r--r-- | src/nvim/sign.c | 4 | ||||
-rw-r--r-- | test/functional/ui/sign_spec.lua | 30 | ||||
-rw-r--r-- | test/old/testdir/test_signs.vim | 6 |
3 files changed, 36 insertions, 4 deletions
diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 1ca0e846a9..605098fb66 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -126,8 +126,8 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr | (has_hl ? MT_FLAG_DECOR_SIGNHL : 0); DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } }; - extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, decor, decor_flags, true, - false, true, true, NULL); + extmark_set(buf, ns, id, MIN(buf->b_ml.ml_line_count, lnum) - 1, 0, -1, -1, + decor, decor_flags, true, false, true, true, NULL); } /// For an existing, placed sign with "id", modify the sign, group or priority. diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index b353b3738a..6f4bf5695d 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -577,4 +577,34 @@ describe('Signs', function() ]]) eq({}, eval('sign_getdefined()')) end) + + it('no crash when unplacing signs beyond end of buffer', function() + exec([[ + sign define S1 text=S1 + sign define S2 text=S2 + sign place 1 line=8 name=S1 + sign place 2 line=9 name=S2 + ]]) + -- Now placed at end of buffer + local s1 = { + grid = [[ + S2^ | + {0:~ }|*12 + | + ]], + } + screen:expect(s1) + -- Signcolumn tracking used to not count signs placed beyond end of buffer here + exec('set signcolumn=auto:9') + screen:expect({ + grid = [[ + S2S1^ | + {0:~ }|*12 + | + ]], + }) + -- Unplacing the sign does not crash by decrementing tracked signs below zero + exec('sign unplace 1') + screen:expect(s1) + end) end) diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim index d7baa7e870..69fefccb3f 100644 --- a/test/old/testdir/test_signs.vim +++ b/test/old/testdir/test_signs.vim @@ -89,8 +89,9 @@ func Test_sign() " Place a sign without specifying the filename or buffer sign place 77 line=9 name=Sign2 let a=execute('sign place') + " Nvim: sign line clamped to buffer length call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" . - \ " line=9 id=77 name=Sign2 priority=10\n", a) + \ " line=4 id=77 name=Sign2 priority=10\n", a) sign unplace * " Check :jump with file=... @@ -799,10 +800,11 @@ func Test_sign_group() set buftype=nofile sign place 25 line=76 name=sign1 priority=99 file=foo let a = execute('sign place') + " Nvim: sign line clamped to buffer length call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . \ " line=10 id=5 name=sign1 priority=10\n" . \ "Signs for foo:\n" . - \ " line=76 id=25 name=sign1 priority=99\n", a) + \ " line=1 id=25 name=sign1 priority=99\n", a) close bwipe foo |