mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	extmarks: fix crash due to invalid column values in inccommand preview
This used to use -1 and MAXCOL values. Make sure in range values are used.
This commit is contained in:
		| @@ -699,21 +699,30 @@ void bufhl_add_hl_pos_offset(buf_T *buf, | |||||||
|  |  | ||||||
|   // TODO(bfredl): if decoration had blocky mode, we could avoid this loop |   // TODO(bfredl): if decoration had blocky mode, we could avoid this loop | ||||||
|   for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) { |   for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) { | ||||||
|  |     int end_off = 0; | ||||||
|     if (pos_start.lnum < lnum && lnum < pos_end.lnum) { |     if (pos_start.lnum < lnum && lnum < pos_end.lnum) { | ||||||
|       hl_start = offset-1; |       // TODO(bfredl): This is quite ad-hoc, but the space between |num| and | ||||||
|       hl_end = MAXCOL; |       // text being highlighted is the indication of \n being part of the | ||||||
|  |       // substituted text. But it would be more consistent to highlight | ||||||
|  |       // a space _after_ the previous line instead (like highlight EOL list | ||||||
|  |       // char) | ||||||
|  |       hl_start = MAX(offset-1, 0); | ||||||
|  |       end_off = 1; | ||||||
|  |       hl_end = 0; | ||||||
|     } else if (lnum == pos_start.lnum && lnum < pos_end.lnum) { |     } else if (lnum == pos_start.lnum && lnum < pos_end.lnum) { | ||||||
|       hl_start = pos_start.col + offset; |       hl_start = pos_start.col + offset; | ||||||
|       hl_end = MAXCOL; |       end_off = 1; | ||||||
|  |       hl_end = 0; | ||||||
|     } else if (pos_start.lnum < lnum && lnum == pos_end.lnum) { |     } else if (pos_start.lnum < lnum && lnum == pos_end.lnum) { | ||||||
|       hl_start = offset-1; |       hl_start = MAX(offset-1, 0); | ||||||
|       hl_end = pos_end.col + offset; |       hl_end = pos_end.col + offset; | ||||||
|     } else if (pos_start.lnum == lnum && pos_end.lnum == lnum) { |     } else if (pos_start.lnum == lnum && pos_end.lnum == lnum) { | ||||||
|       hl_start = pos_start.col + offset; |       hl_start = pos_start.col + offset; | ||||||
|       hl_end = pos_end.col + offset; |       hl_end = pos_end.col + offset; | ||||||
|     } |     } | ||||||
|     (void)extmark_add_decoration(buf, (uint64_t)src_id, hl_id, |     (void)extmark_add_decoration(buf, (uint64_t)src_id, hl_id, | ||||||
|                                  (int)lnum-1, hl_start, (int)lnum-1, hl_end, |                                  (int)lnum-1, hl_start, | ||||||
|  |                                  (int)lnum-1+end_off, hl_end, | ||||||
|                                  VIRTTEXT_EMPTY); |                                  VIRTTEXT_EMPTY); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ local wait = helpers.wait | |||||||
| local nvim = helpers.nvim | local nvim = helpers.nvim | ||||||
| local sleep = helpers.sleep | local sleep = helpers.sleep | ||||||
| local nvim_dir = helpers.nvim_dir | local nvim_dir = helpers.nvim_dir | ||||||
|  | local assert_alive = helpers.assert_alive | ||||||
|  |  | ||||||
| local default_text = [[ | local default_text = [[ | ||||||
|   Inc substitution on |   Inc substitution on | ||||||
| @@ -84,6 +85,7 @@ local function common_setup(screen, inccommand, text) | |||||||
|       [14] = {foreground = Screen.colors.White, background = Screen.colors.Red}, |       [14] = {foreground = Screen.colors.White, background = Screen.colors.Red}, | ||||||
|       [15] = {bold=true, foreground=Screen.colors.Blue}, |       [15] = {bold=true, foreground=Screen.colors.Blue}, | ||||||
|       [16] = {background=Screen.colors.Grey90},  -- cursorline |       [16] = {background=Screen.colors.Grey90},  -- cursorline | ||||||
|  |       [17] = {foreground = Screen.colors.Blue1}, | ||||||
|       vis  = {background=Screen.colors.LightGrey} |       vis  = {background=Screen.colors.LightGrey} | ||||||
|     }) |     }) | ||||||
|   end |   end | ||||||
| @@ -2291,6 +2293,76 @@ describe(":substitute", function() | |||||||
|     ]]) |     ]]) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   it("inccommand=split, contraction of two subsequent NL chars", function() | ||||||
|  |     -- luacheck: push ignore 611 | ||||||
|  |     local text = [[ | ||||||
|  |       AAA AA | ||||||
|  |        | ||||||
|  |       BBB BB | ||||||
|  |        | ||||||
|  |       CCC CC | ||||||
|  |        | ||||||
|  | ]] | ||||||
|  |     -- luacheck: pop | ||||||
|  |  | ||||||
|  |     -- This used to crash, but more than 20 highlight entries are required | ||||||
|  |     -- to reproduce it (so that the marktree has multiple nodes) | ||||||
|  |     common_setup(screen, "split", string.rep(text,10)) | ||||||
|  |     feed(":%s/\\n\\n/<c-v><c-m>/g") | ||||||
|  |     screen:expect{grid=[[ | ||||||
|  |       CCC CC                        | | ||||||
|  |       AAA AA                        | | ||||||
|  |       BBB BB                        | | ||||||
|  |       CCC CC                        | | ||||||
|  |                                     | | ||||||
|  |       {11:[No Name] [+]                 }| | ||||||
|  |       | 1| AAA AA                   | | ||||||
|  |       | 2|{12: }BBB BB                   | | ||||||
|  |       | 3|{12: }CCC CC                   | | ||||||
|  |       | 4|{12: }AAA AA                   | | ||||||
|  |       | 5|{12: }BBB BB                   | | ||||||
|  |       | 6|{12: }CCC CC                   | | ||||||
|  |       | 7|{12: }AAA AA                   | | ||||||
|  |       {10:[Preview]                     }| | ||||||
|  |       :%s/\n\n/{17:^M}/g^                 | | ||||||
|  |     ]]} | ||||||
|  |     assert_alive() | ||||||
|  |   end) | ||||||
|  |  | ||||||
|  |   it("inccommand=nosplit, contraction of two subsequent NL chars", function() | ||||||
|  |     -- luacheck: push ignore 611 | ||||||
|  |     local text = [[ | ||||||
|  |       AAA AA | ||||||
|  |        | ||||||
|  |       BBB BB | ||||||
|  |        | ||||||
|  |       CCC CC | ||||||
|  |        | ||||||
|  | ]] | ||||||
|  |     -- luacheck: pop | ||||||
|  |  | ||||||
|  |     common_setup(screen, "nosplit", string.rep(text,10)) | ||||||
|  |     feed(":%s/\\n\\n/<c-v><c-m>/g") | ||||||
|  |     screen:expect{grid=[[ | ||||||
|  |       CCC CC                        | | ||||||
|  |       AAA AA                        | | ||||||
|  |       BBB BB                        | | ||||||
|  |       CCC CC                        | | ||||||
|  |       AAA AA                        | | ||||||
|  |       BBB BB                        | | ||||||
|  |       CCC CC                        | | ||||||
|  |       AAA AA                        | | ||||||
|  |       BBB BB                        | | ||||||
|  |       CCC CC                        | | ||||||
|  |       AAA AA                        | | ||||||
|  |       BBB BB                        | | ||||||
|  |       CCC CC                        | | ||||||
|  |                                     | | ||||||
|  |       :%s/\n\n/{17:^M}/g^                 | | ||||||
|  |     ]]} | ||||||
|  |     assert_alive() | ||||||
|  |   end) | ||||||
|  |  | ||||||
|   it("inccommand=split, multibyte text", function() |   it("inccommand=split, multibyte text", function() | ||||||
|     common_setup(screen, "split", multibyte_text) |     common_setup(screen, "split", multibyte_text) | ||||||
|     feed(":%s/£.*ѫ/X¥¥") |     feed(":%s/£.*ѫ/X¥¥") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Björn Linse
					Björn Linse