aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/buffer_defs.h4
-rw-r--r--src/nvim/eval.lua4
-rw-r--r--src/nvim/ex_cmds.c5
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/getchar.c93
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/main.c10
-rw-r--r--src/nvim/quickfix.c7
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/test_quickfix.vim11
10 files changed, 81 insertions, 59 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 69cefe2247..4b0e680c25 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -133,14 +133,14 @@ typedef struct buffheader buffheader_T;
*/
struct buffblock {
buffblock_T *b_next; // pointer to next buffblock
- char_u b_str[1]; // contents (actually longer)
+ char_u b_str[]; // contents (flexible array)
};
/*
* header used for the stuff buffer and the redo buffer
*/
struct buffheader {
- buffblock_T bh_first; // first (dummy) block of list
+ buffblock_T *bh_first; // first block of the list
buffblock_T *bh_curr; // buffblock for appending
size_t bh_index; // index for reading
size_t bh_space; // space in bh_curr for appending
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index f36a7ea6c0..6159103767 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -20,10 +20,10 @@ return {
['and']={args=2},
api_info={},
append={args=2},
- argc={},
+ argc={args={0, 1}},
argidx={},
arglistid={args={0, 2}},
- argv={args={0, 1}},
+ argv={args={0, 2}},
asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc
assert_beeps={args={1, 2}},
assert_equal={args={2, 3}},
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 30667b64e5..71ed5f6ec1 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1934,8 +1934,9 @@ void do_wqall(exarg_T *eap)
int error = 0;
int save_forceit = eap->forceit;
- if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall)
- exiting = TRUE;
+ if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) {
+ exiting = true;
+ }
FOR_ALL_BUFFERS(buf) {
if (!bufIsChanged(buf)) {
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0e8455bb07..a494463f89 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6018,7 +6018,7 @@ static void ex_highlight(exarg_T *eap)
*/
void not_exiting(void)
{
- exiting = FALSE;
+ exiting = false;
}
static bool before_quit_autocmds(win_T *wp, bool quit_all, int forceit)
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 13700328fd..465c41457a 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -77,15 +77,15 @@ FileDescriptor *scriptin[NSCRIPT] = { NULL };
#define MINIMAL_SIZE 20 /* minimal size for b_str */
-static buffheader_T redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
-static buffheader_T old_redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
-static buffheader_T recordbuff = { { NULL, { NUL } }, NULL, 0, 0 };
+static buffheader_T redobuff = { NULL, NULL, 0, 0 };
+static buffheader_T old_redobuff = { NULL, NULL, 0, 0 };
+static buffheader_T recordbuff = { NULL, NULL, 0, 0 };
// First read ahead buffer. Used for translated commands.
-static buffheader_T readbuf1 = {{NULL, {NUL}}, NULL, 0, 0};
+static buffheader_T readbuf1 = { NULL, NULL, 0, 0 };
// Second read ahead buffer. Used for redo.
-static buffheader_T readbuf2 = {{NULL, {NUL}}, NULL, 0, 0};
+static buffheader_T readbuf2 = { NULL, NULL, 0, 0 };
static int typeahead_char = 0; /* typeahead char that's not flushed */
@@ -163,11 +163,12 @@ void free_buff(buffheader_T *buf)
{
buffblock_T *p, *np;
- for (p = buf->bh_first.b_next; p != NULL; p = np) {
+ for (p = buf->bh_first; p != NULL; p = np) {
np = p->b_next;
xfree(p);
}
- buf->bh_first.b_next = NULL;
+ buf->bh_first = NULL;
+ buf->bh_curr = NULL;
}
/*
@@ -181,18 +182,21 @@ static char_u *get_buffcont(buffheader_T *buffer,
size_t count = 0;
char_u *p = NULL;
char_u *p2;
- char_u *str;
- /* compute the total length of the string */
- for (buffblock_T *bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
+ // compute the total length of the string
+ for (const buffblock_T *bp = buffer->bh_first; bp != NULL; bp = bp->b_next) {
count += STRLEN(bp->b_str);
+ }
if (count || dozero) {
p = xmalloc(count + 1);
p2 = p;
- for (buffblock_T *bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
- for (str = bp->b_str; *str; )
+ for (const buffblock_T *bp = buffer->bh_first;
+ bp != NULL; bp = bp->b_next) {
+ for (const char_u *str = bp->b_str; *str;) {
*p2++ = *str++;
+ }
+ }
*p2 = NUL;
}
return p;
@@ -257,16 +261,16 @@ static void add_buff(buffheader_T *const buf, const char *const s,
return;
}
- if (buf->bh_first.b_next == NULL) { // first add to list
+ if (buf->bh_first == NULL) { // first add to list
buf->bh_space = 0;
- buf->bh_curr = &(buf->bh_first);
+ buf->bh_curr = NULL;
} else if (buf->bh_curr == NULL) { // buffer has already been read
IEMSG(_("E222: Add to read buffer"));
return;
} else if (buf->bh_index != 0) {
- memmove(buf->bh_first.b_next->b_str,
- buf->bh_first.b_next->b_str + buf->bh_index,
- STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1);
+ memmove(buf->bh_first->b_str,
+ buf->bh_first->b_str + buf->bh_index,
+ STRLEN(buf->bh_first->b_str + buf->bh_index) + 1);
}
buf->bh_index = 0;
@@ -281,13 +285,19 @@ static void add_buff(buffheader_T *const buf, const char *const s,
} else {
len = (size_t)slen;
}
- buffblock_T *p = xmalloc(sizeof(buffblock_T) + len);
+ buffblock_T *p = xmalloc(sizeof(buffblock_T) + len + 1);
buf->bh_space = len - (size_t)slen;
STRLCPY(p->b_str, s, slen + 1);
- p->b_next = buf->bh_curr->b_next;
- buf->bh_curr->b_next = p;
- buf->bh_curr = p;
+ if (buf->bh_curr == NULL) {
+ p->b_next = NULL;
+ buf->bh_first = p;
+ buf->bh_curr = p;
+ } else {
+ p->b_next = buf->bh_curr->b_next;
+ buf->bh_curr->b_next = p;
+ buf->bh_curr = p;
+ }
}
return;
}
@@ -356,17 +366,17 @@ static int read_readbuffers(int advance)
static int read_readbuf(buffheader_T *buf, int advance)
{
char_u c;
- buffblock_T *curr;
- if (buf->bh_first.b_next == NULL) /* buffer is empty */
+ if (buf->bh_first == NULL) { // buffer is empty
return NUL;
+ }
- curr = buf->bh_first.b_next;
+ buffblock_T *const curr = buf->bh_first;
c = curr->b_str[buf->bh_index];
if (advance) {
if (curr->b_str[++buf->bh_index] == NUL) {
- buf->bh_first.b_next = curr->b_next;
+ buf->bh_first = curr->b_next;
xfree(curr);
buf->bh_index = 0;
}
@@ -379,12 +389,12 @@ static int read_readbuf(buffheader_T *buf, int advance)
*/
static void start_stuff(void)
{
- if (readbuf1.bh_first.b_next != NULL) {
- readbuf1.bh_curr = &(readbuf1.bh_first);
+ if (readbuf1.bh_first != NULL) {
+ readbuf1.bh_curr = readbuf1.bh_first;
readbuf1.bh_space = 0;
}
- if (readbuf2.bh_first.b_next != NULL) {
- readbuf2.bh_curr = &(readbuf2.bh_first);
+ if (readbuf2.bh_first != NULL) {
+ readbuf2.bh_curr = readbuf2.bh_first;
readbuf2.bh_space = 0;
}
}
@@ -394,7 +404,8 @@ static void start_stuff(void)
*/
int stuff_empty(void)
{
- return (readbuf1.bh_first.b_next == NULL && readbuf2.bh_first.b_next == NULL);
+ return (readbuf1.bh_first == NULL
+ && readbuf2.bh_first == NULL);
}
/*
@@ -403,7 +414,7 @@ int stuff_empty(void)
*/
int readbuf1_empty(void)
{
- return (readbuf1.bh_first.b_next == NULL);
+ return (readbuf1.bh_first == NULL);
}
/*
@@ -461,7 +472,7 @@ void ResetRedobuff(void)
if (!block_redo) {
free_buff(&old_redobuff);
old_redobuff = redobuff;
- redobuff.bh_first.b_next = NULL;
+ redobuff.bh_first = NULL;
}
}
@@ -474,7 +485,7 @@ void CancelRedo(void)
if (!block_redo) {
free_buff(&redobuff);
redobuff = old_redobuff;
- old_redobuff.bh_first.b_next = NULL;
+ old_redobuff.bh_first = NULL;
start_stuff();
while (read_readbuffers(TRUE) != NUL) {
}
@@ -486,9 +497,9 @@ void CancelRedo(void)
void saveRedobuff(save_redo_T *save_redo)
{
save_redo->sr_redobuff = redobuff;
- redobuff.bh_first.b_next = NULL;
+ redobuff.bh_first = NULL;
save_redo->sr_old_redobuff = old_redobuff;
- old_redobuff.bh_first.b_next = NULL;
+ old_redobuff.bh_first = NULL;
// Make a copy, so that ":normal ." in a function works.
char *const s = (char *)get_buffcont(&save_redo->sr_redobuff, false);
@@ -668,12 +679,10 @@ static int read_redo(bool init, bool old_redo)
int i;
if (init) {
- if (old_redo)
- bp = old_redobuff.bh_first.b_next;
- else
- bp = redobuff.bh_first.b_next;
- if (bp == NULL)
+ bp = old_redo ? old_redobuff.bh_first : redobuff.bh_first;
+ if (bp == NULL) {
return FAIL;
+ }
p = bp->b_str;
return OK;
}
@@ -1206,9 +1215,9 @@ void save_typeahead(tasave_T *tp)
old_char = -1;
tp->save_readbuf1 = readbuf1;
- readbuf1.bh_first.b_next = NULL;
+ readbuf1.bh_first = NULL;
tp->save_readbuf2 = readbuf2;
- readbuf2.bh_first.b_next = NULL;
+ readbuf2.bh_first = NULL;
}
/*
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 4fce02613c..dbbc7cdafd 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -510,7 +510,7 @@ EXTERN int sc_col; /* column for shown command */
// First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished.
EXTERN int starting INIT(= NO_SCREEN);
// true when planning to exit. Might keep running if there is a changed buffer.
-EXTERN int exiting INIT(= false);
+EXTERN bool exiting INIT(= false);
// is stdin a terminal?
EXTERN int stdin_isatty INIT(= true);
// is stdout a terminal?
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 2c182abb96..55be97d3f4 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -584,9 +584,7 @@ int main(int argc, char **argv)
void getout(int exitval)
FUNC_ATTR_NORETURN
{
- tabpage_T *tp, *next_tp;
-
- exiting = TRUE;
+ exiting = true;
/* When running in Ex mode an error causes us to exit with a non-zero exit
* code. POSIX requires this, although it's not 100% clear from the
@@ -603,8 +601,10 @@ void getout(int exitval)
hash_debug_results();
if (get_vim_var_nr(VV_DYING) <= 1) {
- /* Trigger BufWinLeave for all windows, but only once per buffer. */
- for (tp = first_tabpage; tp != NULL; tp = next_tp) {
+ const tabpage_T *next_tp;
+
+ // Trigger BufWinLeave for all windows, but only once per buffer.
+ for (const tabpage_T *tp = first_tabpage; tp != NULL; tp = next_tp) {
next_tp = tp->tp_next;
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
if (wp->w_buffer == NULL) {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 0e4fa0afc6..3c744310b3 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -5368,8 +5368,11 @@ void ex_cexpr(exarg_T *eap)
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name,
curbuf->b_fname, true, curbuf);
}
- if (res > 0 && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)) {
- qf_jump(qi, 0, 0, eap->forceit); // display first error
+ if (res > 0
+ && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
+ && qi == GET_LOC_LIST(curwin)) {
+ // Jump to the first error if autocmds didn't free the list.
+ qf_jump(qi, 0, 0, eap->forceit);
}
} else {
EMSG(_("E777: String or List expected"));
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 7b1f0f59cc..fe9e0bc9c8 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -32,14 +32,12 @@ NEW_TESTS_ALOT := test_alot_utf8 test_alot
NEW_TESTS_IN_ALOT := $(shell sed '/^source/ s/^source //;s/\.vim$$//' test_alot*.vim)
# Ignored tests.
# test_alot_latin: Nvim does not allow setting encoding.
-# test_arglist: ported to Lua, but kept for easier merging.
# test_autochdir: ported to Lua, but kept for easier merging.
# test_eval_func: used as include in old-style test (test_eval.in).
# test_listlbr: Nvim does not allow setting encoding.
# test_largefile: uses too much resources to run on CI.
NEW_TESTS_IGNORE := $(NEW_TESTS_IN_ALOT) $(NEW_TESTS_ALOT) \
test_alot_latin \
- test_arglist \
test_autochdir \
test_eval_func \
test_listlbr \
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index fcb02d3437..4d78c67f5c 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -3373,6 +3373,17 @@ func Test_lbuffer_with_bwipe()
augroup END
endfunc
+func Test_setloclist_in_aucmd()
+ " This was using freed memory.
+ augroup nasty
+ au * * call setloclist(0, [], 'f')
+ augroup END
+ lexpr "x"
+ augroup nasty
+ au!
+ augroup END
+endfunc
+
" Tests for the "CTRL-W <CR>" command.
func Xview_result_split_tests(cchar)
call s:setup_commands(a:cchar)