mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(column): clamp line number for legacy signs
Problem:  Legacy :sign API still allows placing signs beyond the end of
          the buffer. This is unaccounted for by the signcolumn tracking
          logic and is disallowed in general for the extmark API which
          implements it now.
Solution: Clamp legacy sign line number to the length of the buffer.
			
			
This commit is contained in:
		| @@ -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. | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Luuk van Baal
					Luuk van Baal