We already use wrappers for allocation, the new `xfree` function is the
equivalent for deallocation and provides a way to fully replace the malloc
implementation used by Neovim.
Problem : Dereference of null pointer @ 1769.
Diagnostic : Real issue.
Rationale : It seems buffer could be null. Not sure, though.
Resolution : Check for buffer null.
This resolution was chosen as it will always work.
But it could be that buffer can't really be null at that
point. autocmd_win is ruled out by close_window, so that
can't be the case. I'm not sure if other windows without
buffers are possible, so leaving it this way.
If it's confirmed buffer can't be null, resolution through
an assert would be possible and this would be FP, not RI.
This commit integrates libvterm with Neovim and implements a terminal emulator
with nvim buffers as the display mechanism. Terminal buffers can be created
using any of the following methods:
- Opening a file with name following the "term://[${cwd}//[${pid}:]]${cmd}"
URI pattern where:
- cwd is the working directory of the process
- pid is the process id. This is just for use in session files where a pid
would have been assigned to the saved buffer title.
- cmd is the command to run
- Invoking the `:terminal` ex command
- Invoking the `termopen` function which returns a job id for automating the
terminal window.
Some extra changes were also implemented to adapt with terminal buffers. Here's
an overview:
- The `main` function now sets a BufReadCmd autocmd to intercept the term:// URI
and spawn the terminal buffer instead of reading the file.
- terminal buffers behave as if the following local buffer options were set:
- `nomodifiable`
- `swapfile`
- `undolevels=-1`
- `bufhidden=hide`
- All commands that delete buffers(`:bun`, `:bd` and `:bw`) behave the same for
terminal buffers, but only work when bang is passed(eg: `:bwipeout!`)
- A new "terminal" mode was added. A consequence is that a new set of mapping
commands were implemented with the "t" prefix(tmap, tunmap, tnoremap...)
- The `edit` function(which enters insert mode) will actually enter terminal
mode if the current buffer is a terminal
- The `put` operator was adapted to send data to the terminal instead of
modifying the buffer directly.
- A window being resized will also trigger a terminal resize if the window
displays the terminal.
Problem : Use after free @ 1795.
Diagnostic : Real issue.
Rationale : prev_curtab can in fact be freed as a result of call
`win_close_othertab(win, free_buf, prev_curtab);`, but it's
later used at
`sprintf(..., tabpage_index(prev_curtab));`.
This was introduced at
3ffc5d81c3.
Resolution : Move prev_idx calculation before the call freeing
prev_curtab.
- Removed term.c, term.h and term_defs.h
- Tests for T_* values were removed. screen.c was simplified as a
consequence(the best strategy for drawing is implemented in the UI layer)
- Redraw functions now call ui.c functions directly. Updates are flushed with
`ui_flush()`
- Removed all termcap options(they now return empty strings for compatibility)
- &term/&ttybuiltin options return a constant value(nvim)
- &t_Co is still available, but it mirrors t_colors directly
- Remove cursor tracking from screen.c and the `screen_start` function. Now the
UI is expected to maintain cursor state across any call, and reset it when
resized.
- Remove unused code
Problem: In some situations, when setting up an environment to trigger an
autocommand, the environment is not properly restored.
Solution: Check the return value of switch_win() and call restore_win()
always. (Daniel Hahler)
https://code.google.com/p/vim/source/detail?r=v7-4-446
Regarding dict_lookup() in eval.c: both definitions are the same, the
only difference being the spacing between the indirection operator and
the indentation level.
Problem : getdigits() currently returns a long, but at most places,
return value is casted (unsafely) into an int. Making casts
safe would introduce a lot of fuss in the form of assertions
checking for limits.
Note : We cannot just change return type to int, because, at some
places, legitimate long values are used. For example, in
diff.c, for line numbers.
Solution : Introduce new functions:
- get_digits() : Gets an intmax_t from a string.
- get_int_digits() : Wrapper for ints.
- get_long_digits() : Wrapper for longs.
And replace getdigits() invocations by the appropiate
wrapper invocations.
Problem: ":sign jump" may use another window even though the file is
already edited in the current window.
Solution: First check if the file is in the current window. (James McCoy)
https://code.google.com/p/vim/source/detail?r=v7-4-487
Problem : Dereference of null pointer @ 1980.
Diagnostic : False positive.
Rationale : I haven't been able to find the real reason why this is
signaled. Nonetheless, I've been able to track down the
introduction of this warning to commit
77135447e0.
The change there affecting this function is just a
transformation maintaining semantics. So, this must be a
FP, though I can't explain why.
Analyzer thinks `win->w_buffer` can be null in line 1980,
following an error path assuming win->w_buffer null at line
1819. Given that `win_close` function was not modified by
mentioned commit, I don't understand why this path is
analyzed after the changes, but not before them. Or if it's
analyzed, why it's discarded before changes but not after
them. I don't see anything in changes to
`close_last_window_tabpage` that should affect to
being able to deduce `win->w_buffer` is not null.
Resolution : Assert buffer not null in `win_close_othertab`.
Function comments state that passed window should have a
buffer that can be hidden, which implies there should be a
buffer.
Reverting changes to `close_last_window_tabpage` in
mentioned commit would be another way to fix this (tried
and worked).
But assert is preferred in this case because flat style
reads better and we have some other way to fix it.
Problem : Dereference of null pointer @ 4978.
Diagnostic : False positive.
Rationale : tabline_height() shouldn't be called when a tab doesn't
exist yet (this is, before initialization).
Resolution : Assert function precondition.
Problem : Dereference of null pointer @ 4512.
Diagnostic : False positive.
Rationale : Suggested error path implies `fr == NULL` after 4504.
That's not possible, because:
- curfr and curfr->next must be both nonnull, as we are
dragging the divider between the two.
- after conditional, fr is one of those two (the one that
grows).
Resolution : Assert fr.
Problem : Dereference of null pointer @ 2196.
Diagnostic : False positive.
Rationale : Suggested error path implies `frp->child == NULL` while
being under condition `frp2->fr_layout == frp->fr_layout`,
which is impossible:
- If frp2 is frp's parent, then frp2's layout is FR_COL or
FR_ROW;
- if frp->child is NULL, the frp's layout is FR_LEAF.
- Therefore, they can't be equal.
Resolution : Assert frp->child not null.
Problem : Dereference of null pointer @ 1268.
Diagnostic : False positive.
Rationale : Suggested error path implies current window's frame to be
the only child of its parent, which is ruled out by
`if (firstwin == lastwin) {` check at the beginning.
Resolution : Assert another child remains after removing current frame.
Strictly, assert is only needed in false branch of
conditional, but we add it the same in the true branch to
reduce reader surprise.
Several forms of a single assert after
`if (firstwin == lastwin) {` were tried, but analyzer
cannot follow implications that way.
Problem: Possible crash when an BufLeave autocommand deletes the buffer.
Solution: Check for the window pointer being valid. Postpone freeing the
window until autocommands are done. (Yasuhiro Matsumoto)
https://code.google.com/p/vim/source/detail?r=v7-4-320
Problem: When 'equalalways' is set a split may report "no room" even though
there is plenty of room.
Solution: Compute the available room properly. (Yukihiro Nakadaira)
https://code.google.com/p/vim/source/detail?r=v7-4-377
Problem: Restoring the window sizes after closing the command line window
doesn't work properly if there are nested splits.
Solution: Restore the sizes twice. (Hirohito Higashi)
https://code.google.com/p/vim/source/detail?r=v7-4-368
Problem: When there are matches to highlight the whole window is redrawn,
which is slow.
Solution: Only redraw everything when lines were inserted or deleted.
Reset b_mod_xlines when needed. (Alexey Radkov)
https://code.google.com/p/vim/source/detail?r=v7-4-349
Problem: When moving the cursor and then switching to another window the
previous window isn't scrolled. (Yukihiro Nakadaira)
Solution: Call update_topline() before leaving the window. (Christian
Brabandt)
https://code.google.com/p/vim/source/detail?r=018df65085f8
Problem: When starting the gui and changing the window size the status line
may not be drawn correctly.
Solution: Catch new_win_height() being called recursively. (Christian
Brabandt)
https://code.google.com/p/vim/source/detail?r=1f288d247548