Commit Graph

781 Commits

Author SHA1 Message Date
33dfb5a383 fix(window): :close may cause Nvim to quit with autocmd and float
Problem:  :close may cause Nvim to quit if an autocommand triggered when
          closing the buffer closes all other non-floating windows and
          there are floating windows.
Solution: Correct the check for the only non-floating window.
2024-03-09 13:38:32 +08:00
d942c2b943 fix(api): handle win_split_ins failure properly
Problem: nvim_win_set_config does not handle failure in win_split_ins properly
yet, which can cause all sorts of issues. Also nvim_open_win and
nvim_win_set_config do not set the error message to the one from win_split_ins.

Solution: handle failure by undoing winframe_remove, like in win_splitmove.
Make sure autocommands from switching to the altwin fire within a valid window,
and ensure they don't screw things up. Set the error message to that of
win_split_ins, if any.

Also change a few other small things, including:

- adjust win_append to take a tabpage_T * argument, which is more consistent
  with win_remove (and also allows us to undo a call to win_remove).

- allow winframe_restore to restore window positions. Useful if `wp` was in a
  different tabpage, as a call to win_comp_pos (which only works for the current
  tabpage) after winframe_restore should no longer be needed.

  Though enter_tabpage calls win_comp_pos anyway, this has the advantage of
  ensuring w_winrow/col remains accurate even before entering the tabpage
  (useful for stuff like win_screenpos, if used on a window in another tabpage).

  (This change should probably also be PR'd to Vim later, even though it doesn't
  use winframe_restore for a `wp` in a different tabpage yet).
2024-03-08 23:24:05 +00:00
832bc5c169 vim-patch:9.1.0130: [security]: UAF if win_split_ins autocommands delete "wp"
Problem:  heap-use-after-free in win_splitmove if Enter/Leave
          autocommands from win_split_ins immediately closes "wp".
Solution: check that "wp" is valid after win_split_ins.
          (Sean Dewar)

abf7030a5c
2024-03-08 23:24:05 +00:00
1c6b693ec1 vim-patch:9.1.0118: Use different restoration strategy in win_splitmove
Problem:  saving and restoring all frames to split-move is overkill now
          that WinNewPre is not fired when split-moving.
Solution: defer the flattening of frames until win_split_ins begins
          reorganising them, and attempt to restore the layout by
          undoing our changes. (Sean Dewar)

704966c254

Adjust winframe_restore to account for Nvim's horizontal separators when the
global statusline is in use. Add a test.
2024-03-08 23:24:04 +00:00
24dfa47e4f vim-patch:partial:9.1.0117: Stop split-moving from firing WinNew and WinNewPre autocommands
Problem:  win_splitmove fires WinNewPre and possibly WinNew when moving
          windows, even though no new windows are created.
Solution: don't fire WinNew and WinNewPre when inserting an existing
          window, even if it isn't the current window. Improve the
          accuracy of related documentation. (Sean Dewar)

96cc4aef3d

Partial as WinNewPre has not been ported yet (it currently has problems anyway).
2024-03-08 23:24:04 +00:00
66f331fef7 vim-patch:9.1.0116: win_split_ins may not check available room
Problem:  win_split_ins has no check for E36 when moving an existing
          window
Solution: check for room and fix the issues in f_win_splitmove()
          (Sean Dewar)

0fd44a5ad8

Omit WSP_FORCE_ROOM, as it's not needed for Nvim's autocmd window, which is
floating. Shouldn't be difficult to port later if it's used for anything else.

Make win_splitmove continue working for turning floating windows into splits.
Move the logic for "unfloating" a float to win_split_ins; unlike splits, no
changes to the window layout are needed before calling it, as floats take no
room in the window layout and cannot affect the e_noroom check.

Add missing tp_curwin-fixing logic for turning external windows into splits, and
add a test.
NOTE: there are other issues with the way "tabpage independence" is implemented
for external windows; namely, some things assume that tp_curwin is indeed a
window within that tabpage, and as such, functions like tabpage_winnr and
nvim_tabpage_get_win currently don't always work for external windows (with the
latter aborting!)

Use last_status over frame_add_statusline, as Nvim's last_status already does
this for all windows in the current tabpage. Adjust restore_full_snapshot_rec to
handle this.
This "restore everything" approach is changed in a future commit anyway, so only
ensure it's robust enough to just pass tests.

Keep check_split_disallowed's current doc comment, as it's actually a bit more
accurate here. (I should probably PR Vim to use this one)

Allow f_win_splitmove to move a floating "wp" into a split; Nvim supports this.
Continue to disallow it from moving the autocommand window into a split (funnily
enough, the check wasn't reachable before, as moving a float was disallowed),
but now return -1 in that case (win_splitmove also returns FAIL for this, but
handling it in f_win_splitmove avoids us needing to switch windows first).

Cherry-pick Test_window_split_no_room fix from v9.1.0121.

Update nvim_win_set_config to handle win_split_ins failure in later commits.
2024-03-08 23:24:04 +00:00
5d58136ccc fix(api): make open_win/win_set_config check if splitting allowed
Problem: splitting is disallowed in some cases to prevent the window layout
changes while a window is closing, but it's not checked for.

Solution: check for this, and set the API error message directly.

(Also sneak in a change to tui.c that got lost from #27352; it's a char* buf,
and the memset is assuming one byte each anyway)
2024-03-08 23:24:03 +00:00
a873f33993 fix(api): open_win fire BufWinEnter for other buffer when !enter && !noautocmd
Problem: BufWinEnter is not fired when not entering a new window, even when a
different buffer is specified and buffer-related autocommands are unblocked
(!noautocmd).

Solution: fire it in the context of the new window and buffer. Do not do it if
the buffer is unchanged, like :{s}buffer.

Be wary of autocommands! For example, it's possible for nvim_win_set_config to
be used in an autocommand to move a window to a different tabpage (in contrast,
things like wincmd T actually create a *new* window, so it may not have been
possible before, meaning other parts of Nvim could assume windows can't do
this... I'd be especially cautious of logic that restores curwin and curtab
without checking if curwin is still valid in curtab, if any such logic exists).

Also, bail early from win_set_buf if setting the temp curwin fails; this
shouldn't be possible, as the callers check that wp is valid, but in case that's
not true, win_set_buf will no longer continue setting a buffer for the wrong
window.

Note that pum_create_float_preview also uses win_set_buf, but from a glance,
doesn't look like it properly checks for autocmds screwing things up (win_enter,
nvim_create_buf...). I haven't addressed that here.

Also adds some test coverage for nvim_open_win autocommands.

Closes #27121.
2024-03-08 23:23:55 +00:00
884470124d fix(float): allow floating window in cmdline area
Problem:  Floats are arbitrarily positioned at 1 row above screen size.
Solution: Position at 1 row above 'cmdheight', only if window is hidden behind the message area.
2024-03-01 16:00:16 +01:00
0eaae1bc05 vim-patch:9.1.0143: [security]: autocmd causes use-after-free in set_curbuf() (#27664)
Problem:  [security]: autocmd cause use-after-free in set_curbuf()
          (kawarimidoll)
Solution: check side-effect of BufLeave autocommand, when the number
          of windows changed, close windows containing buffers that will
          be wiped, if curbuf changed unexpectedly make sure b_nwindows
          is decremented otherwise it cannot be wiped

set_curbuf() already makes some efforts to ensure the BufLeave
autocommands do not cause issues.  However there are still 2 issues
that are not taken care of:

1) If a BufLeave autocommand opens a new window containing the same
buffer as that is going got be closed in close_buffer() a bit later,
we suddenly have another window open, containing a free'd buffer.  So we
must check if the number of windows changed and if it does (and the
current buffer is going to be wiped (according to the 'bufhidden'
setting), let's immediately close all windows containing the current
buffer using close_windows()

2) If a BufLeave autocommand changes our current buffer (displays it in
the current window), buf->b_nwindow will be incremented. As part of
set_curbuf() we will however enter another buffer soon, which means, the
newly created curbuf will have b_nwindows still have set, even so the
buffer is no longer displayed in a window. This causes later problems,
because it will no longer be possible to wipe such a buffer. So just
before entering the final buffer, check if the curbuf changed when
calling the BufLeave autocommand and if it does (and curbuf is still
valid), decrement curbuf->b_nwindows.

Both issues can be verified using the provided test (however the second
issue only because such an impacted buffer won't be wiped, causing
futher issues in later tests).

fixes: vim/vim#13839
closes: vim/vim#14104

55f8bba73b

Co-authored-by: Christian Brabandt <cb@256bit.org>
2024-02-29 08:33:02 +08:00
1c032ad703 feat(extmark): window scoped extmark
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
2024-02-21 16:11:50 +01:00
f1f8fa850f refactor: rename w_float_config to w_config #27419
Follows up on rename of `FloatConfig` to `WinConfig` in #27397.
2024-02-10 13:06:01 -08:00
5bbb733a1b vim-patch:9.1.0089: qsort() comparison functions should be transitive
Problem:  qsort() comparison functions should be transitive
Solution: Do not subtract values, but rather use explicit comparisons

Improve qsort() comparison functions

There has been a recent report on qsort() causing out-of-bounds read &
write in glibc for non transitive comparison functions
https://www.qualys.com/2024/01/30/qsort.txt

Even so the bug is in glibc's implementation of the qsort() algorithm,
it's bad style to just use substraction for the comparison functions,
which may cause overflow issues and as hinted at in OpenBSD's manual
page for qsort(): "It is almost always an error to use subtraction to
compute the return value of the comparison function."

So check the qsort() comparison functions and change them to be safe.

closes: vim/vim#13980

e06e437665

Co-authored-by: Christian Brabandt <cb@256bit.org>
2024-02-10 21:55:51 +08:00
607606e3bb Merge pull request #27398 from bfredl/arena2
refactor(api): use arena for more stuff
2024-02-10 12:07:37 +01:00
44ec4b5b18 refactor: rename FloatConfig to WinConfig #27397
`FloatConfig` is no longer used only for floats, so the name is counterintuitive.

Followup to #25550
2024-02-09 08:17:10 -08:00
e0e5b7f0ba refactor(api): make cstr_as_string accept "const char*"
In the context a String inside an Object/Dictionary etc is consumed,
it is considered to be read-only.
2024-02-09 15:11:21 +01:00
6bba4beced feat(api): make nvim_open_win support non-floating windows (#25550)
Adds support to `nvim_open_win` and `nvim_win_set_config` for creating
and manipulating split (non-floating) windows.
2024-02-01 11:43:35 +08:00
ca9f6f5694 feat(api): add nvim_tabpage_set_win (#27222)
Allows setting the current window of a non-current tabpage
without switching tabpages.
2024-01-29 15:18:33 +08:00
d6f7fa14c5 refactor(window.c): add a few more assertions (#27249) 2024-01-29 10:05:33 +08:00
cf140fb25b vim-patch:9.1.0047: issues with temp curwin/buf while cmdwin is open
Problem:  Things that temporarily change/restore curwin/buf (e.g:
          win_execute, some autocmds) may break assumptions that
          curwin/buf is the cmdwin when "cmdwin_type != 0", causing
          issues.

Solution: Expose the cmdwin's real win/buf and check that instead. Also
          try to ensure these variables are NULL if "cmdwin_type == 0",
          allowing them to be used directly in most cases without
          checking cmdwin_type. (Sean Dewar)

Reset and save `cmdwin_old_curwin` in a similar fashion.
Apply suitable changes for API functions and add Lua tests.

988f74311c
2024-01-28 12:29:26 +00:00
bf9e92c81c fix(events): check for WinResized/WinScrolled in terminal mode (#27226) 2024-01-27 15:18:41 +08:00
2fce95ec43 vim-patch:9.1.0033: Insert mode not stopped if closing prompt buffer modifies hidden buffer (#27051)
Problem:  Insert mode not stopped if an autocommand modifies a hidden
          buffer while closing a prompt buffer.
Solution: Don't set b_prompt_insert if stop_insert_mode is already set.
          (zeertzjq)

closes: vim/vim#13872

96958366ad
2024-01-17 08:18:52 +08:00
1813661a61 refactor(IWYU): fix headers
Remove `export` pramgas from defs headers as it causes IWYU to believe
that the definitions from the defs headers comes from main header, which
is not what we really want.
2024-01-11 21:37:23 +01:00
aeb053907d refactor(options): use schar_T representation for fillchars and listchars
A bit big, but practically it was a lot simpler to change over all
fillchars and all listchars at once, to not need to maintain two
parallel implementations.

This is mostly an internal refactor, but it also removes an arbitrary
limitation: that 'fillchars' and 'listchars' values can only be
single-codepoint characters. Now any character which fits into a single
screen cell can be used.
2024-01-08 14:37:55 +01:00
bdfea2a891 vim-patch:9.1.0001: when closing window, wincmd p may fail
Avoid `prevwin == curwin` when closing `curwin`

Problem:  When closing the current window (or when moving it to a tabpage), the
          previous window may refer to the new current window
          (`winnr() == winnr('#')`) if that window is selected as the
          new current window.

Solution: Set `prevwin = NULL` when switching away from an invalid `curwin` and
          the target window was the `prevwin`.
          (Sean Dewar)

related: vim/vim#4537
closes: vim/vim#13762

bf44b69d1f

Co-authored-by: Sean Dewar <seandewar@users.noreply.github.com>
2024-01-03 23:09:55 +01:00
c89292fcb7 refactor: follow style guide 2023-12-30 12:45:38 +01:00
547ccc2681 refactor(options): remove side effects from check_num_option_bounds() 2023-12-24 11:22:25 +06:00
af93a74a0f refactor: run IWYU on entire repo
Reference: https://github.com/neovim/neovim/issues/6371.
2023-12-21 17:38:42 +01:00
6cb78e2d1c docs: add style rule regarding initialization
Specifically, specify that each initialization should be done on a
separate line.
2023-12-18 16:22:13 +01:00
69bc519b53 refactor: move non-symbols to defs.h headers 2023-12-17 19:03:18 +01:00
19fed6bde1 vim-patch:9.0.2168: Moving tabpages on :drop may cause an endless loop (#26605)
Problem:  Moving tabpages on :drop may cause an endless loop
Solution: Disallow moving tabpages on :drop when cleaning up the arglist
          first

Moving tabpages during drop command may cause an endless loop

When executing a :tab drop command, Vim will close all windows not in
the argument list. This triggers various autocommands. If a user has
created an 'au Tabenter * :tabmove -' autocommand, this can cause Vim to
end up in an endless loop, when trying to iterate over all tabs (which
would trigger the tabmove autocommand, which will change the tpnext
pointer, etc).

So instead of blocking all autocommands before we actually try to edit
the given file, lets simply disallow to move tabpages around. Otherwise,
we may change the expected number of events triggered during a :drop
command, which users may rely on (there is actually a test, that expects
various TabLeave/TabEnter autocommands) and would therefore be a
backwards incompatible change.

Don't make this an error, as this could trigger several times during the
drop command, but silently ignore the :tabmove command in this case (and
it should in fact finally trigger successfully when loading the given
file in a new tab). So let's just be quiet here instead.

fixes:  vim/vim#13676
closes: vim/vim#13686

df12e39b8b

Co-authored-by: Christian Brabandt <cb@256bit.org>
2023-12-16 21:30:08 +08:00
e38027ef69 feat(ui): completeopt support popup like vim 2023-12-16 18:59:59 +08:00
6346987601 refactor(options): reduce findoption() usage
Problem: Many places in the code use `findoption()` to access an option using its name, even if the option index is available. This is very slow because it requires looping through the options array over and over.

Solution: Use option index instead of name wherever possible. Also introduce an `OptIndex` enum which contains the index for every option as enum constants, this eliminates the need to pass static option names as strings.
2023-12-09 17:54:43 +06:00
7402655132 vim-patch:9.0.2140: [security]: use-after-free in win-enter
Problem:  [security]: use-after-free in win-enter
Solution: validate window pointer before calling win_enter()

win_goto() may stop visual mode, if it is active. However, this may in
turn trigger the ModeChanged autocommand, which could potentially free
the wp pointer which was valid before now became stale and points to now
freed memory.

So before calling win_enter(), let's verify one more time, that the
wp pointer still points to a valid window structure.

Reported by @henices, thanks!

eec0c2b3a4

Co-authored-by: Christian Brabandt <cb@256bit.org>
2023-12-02 10:41:31 +08:00
543e0256c1 build: don't define FUNC_ATTR_* as empty in headers (#26317)
FUNC_ATTR_* should only be used in .c files with generated headers.
Defining FUNC_ATTR_* as empty in headers causes misuses of them to be
silently ignored. Instead don't define them by default, and only define
them as empty after a .c file has included its generated header.
2023-11-30 15:51:05 +08:00
640680ccce vim-patch:9.0.2134: ml_get error when scrolling (#26264)
Problem:  ml_get error when scrolling after delete
Solution: mark topline to be validated in main_loop
          if it is larger than current buffers line
          count

reset_lnums() is called after e.g. TextChanged autocommands and it may
accidentally cause curwin->w_topline to become invalid, e.g. if the
autocommand has deleted some lines.

So verify that curwin->w_topline points to a valid line and if not, mark
the window to have w_topline recalculated in main_loop() in
update_topline() after reset_lnums() returns.

fixes: vim/vim#13568
fixes: vim/vim#13578

c4ffeddfe5

The error doesn't happen in Nvim because Nvim triggers TextChanged after
calling update_topline().

Co-authored-by: Christian Brabandt <cb@256bit.org>
2023-11-29 13:24:24 +08:00
64b53b71ba refactor(IWYU): create normal_defs.h (#26293) 2023-11-29 12:10:42 +08:00
79b6ff28ad refactor: fix headers with IWYU 2023-11-28 22:23:56 +01:00
6c14ae6bfa refactor: rename types.h to types_defs.h 2023-11-27 21:57:51 +01:00
f4aedbae4c build(IWYU): fix includes for undo_defs.h 2023-11-27 19:33:17 +01:00
8b428ca8b7 build(IWYU): fix includes for func_attr.h 2023-11-27 18:06:57 +01:00
38a20dd89f build(IWYU): replace most private mappings with pragmas (#26247) 2023-11-27 20:58:37 +08:00
574d25642f refactor: move Arena and ArenaMem to memory_defs.h (#26240) 2023-11-27 17:21:58 +08:00
a6e3d93421 refactor: enable formatting for ternaries
This requires removing the "Inner expression should be aligned" rule
from clint as it prevents essentially any formatting regarding ternary
operators.
2023-11-20 19:57:09 +01:00
790bd4d585 vim-patch:9.0.2106: [security]: Use-after-free in win_close()
Problem:  [security]: Use-after-free in win_close()
Solution: Check window is valid, before accessing it

If the current window structure is no longer valid (because a previous
autocommand has already freed this window), fail and return before
attempting to set win->w_closing variable.

Add a test to trigger ASAN in CI

25aabc2b8e

Co-authored-by: Christian Brabandt <cb@256bit.org>
2023-11-17 09:59:22 +08:00
1274380029 vim-patch:9.0.1864: still crash with bt_quickfix1_poc
Problem:  crash with bt_quickfix1_poc when cleaning up
          and EXITFREE is defined
Solution: Test if buffer is valid in a window, else close
          window directly, don't try to access buffer properties

While at it, increase the crash timeout slightly, so that CI has a
chance to finish processing the test_crash() test.

623ba31821

Co-authored-by: Christian Brabandt <cb@256bit.org>
2023-11-17 09:54:03 +08:00
bb4b4576e3 refactor: iwyu (#26062) 2023-11-16 10:55:54 +08:00
326d46f690 refactor: move some functions to winfloat.c (#26020) 2023-11-16 09:54:47 +08:00
422af9c5c5 vim-patch:8.1.1521: when a popup window is closed the buffer remains (#26024)
Problem:    When a popup window is closed the buffer remains.
Solution:   Wipe out the buffer.

7c7f01e2b2

Co-authored-by: Bram Moolenaar <Bram@vim.org>
2023-11-13 15:41:22 +08:00
353a4be7e8 build: remove PVS
We already have an extensive suite of static analysis tools we use,
which causes a fair bit of redundancy as we get duplicate warnings. PVS
is also prone to give false warnings which creates a lot of work to
identify and disable.
2023-11-12 21:26:39 +01:00