aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/sign.c4
-rw-r--r--test/functional/ui/sign_spec.lua30
-rw-r--r--test/old/testdir/test_signs.vim6
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