From 295a264b65bd072bf858496e0e5de83d5b1f5ffa Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 18 Jan 2023 15:12:45 +0800 Subject: [PATCH 1/2] fix(statusline): don't leak memory with zero-width click labels A zero-width click label isn't assigned to any click definition, so its function name should be freed when filling click definitions. --- src/nvim/statusline.c | 16 ++++++++++++---- test/functional/ui/statusline_spec.lua | 10 ++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 0639615b8b..772b302023 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -231,8 +231,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r }; for (int i = 0; click_recs[i].start != NULL; i++) { len += vim_strnsize(buf, (int)(click_recs[i].start - buf)); - while (col < len) { - click_defs[col++] = cur_click_def; + if (col < len) { + while (col < len) { + click_defs[col++] = cur_click_def; + } + } else { + xfree(cur_click_def.func); } buf = (char *)click_recs[i].start; cur_click_def = click_recs[i].def; @@ -242,8 +246,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r cur_click_def.type = kStlClickDisabled; } } - while (col < width) { - click_defs[col++] = cur_click_def; + if (col < width) { + while (col < width) { + click_defs[col++] = cur_click_def; + } + } else { + xfree(cur_click_def.func); } } diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index 549ebbde06..26a34f6d14 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -164,6 +164,16 @@ describe('statusline clicks', function() meths.input_mouse('right', 'press', '', 0, 6, 5) eq('0 1 r', eval("g:testvar")) end) + + it('no memory leak with zero-width click labels', function() + command([[ + let &stl = '%@Test@%T%@MyClickFunc@%=%T%@Test@' + ]]) + meths.input_mouse('left', 'press', '', 0, 6, 0) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 39) + eq('0 1 r', eval("g:testvar")) + end) end) describe('global statusline', function() From 01ddc097474627f35cc34fb7015dd26505e2ddcc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 18 Jan 2023 19:10:58 +0800 Subject: [PATCH 2/2] fix(statusline): don't leak memory with truncated click labels --- src/nvim/statusline.c | 5 +++++ test/functional/ui/statusline_spec.lua | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 772b302023..29ce8dab71 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1987,6 +1987,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n // the truncation point for (int i = 0; i < itemcnt; i++) { if (stl_items[i].start > trunc_p) { + for (int j = i; j < itemcnt; j++) { + if (stl_items[j].type == ClickFunc) { + XFREE_CLEAR(stl_items[j].cmd); + } + } itemcnt = i; break; } diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index 26a34f6d14..1c184ff27d 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -174,6 +174,14 @@ describe('statusline clicks', function() meths.input_mouse('right', 'press', '', 0, 6, 39) eq('0 1 r', eval("g:testvar")) end) + + it('no memory leak with truncated click labels', function() + command([[ + let &stl = '%@MyClickFunc@foo%X' .. repeat('a', 40) .. '%