aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml4
-rw-r--r--ci/common/build.sh7
-rw-r--r--ci/common/test.sh8
-rw-r--r--src/.tsan-suppressions2
-rw-r--r--src/nvim/README.md2
-rw-r--r--src/nvim/edit.c155
-rw-r--r--src/nvim/eval.c8
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/screen.c2
-rwxr-xr-xsrc/nvim/testdir/runnvim.sh2
-rw-r--r--src/nvim/ui_compositor.c22
-rw-r--r--test/functional/provider/python3_spec.lua6
12 files changed, 122 insertions, 100 deletions
diff --git a/.travis.yml b/.travis.yml
index f234c89c26..9d8a2ea59b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,7 +30,7 @@ env:
-DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/cmake/i386-linux-gnu.toolchain.cmake"
# Environment variables for Clang sanitizers.
- ASAN_OPTIONS="detect_leaks=1:check_initialization_order=1:log_path=$LOG_DIR/asan"
- - TSAN_OPTIONS="log_path=$LOG_DIR/tsan"
+ - TSAN_OPTIONS="log_path=$LOG_DIR/tsan:suppressions=$TRAVIS_BUILD_DIR/src/.tsan-suppressions"
- UBSAN_OPTIONS="print_stacktrace=1 log_path=$LOG_DIR/ubsan"
# Environment variables for Valgrind.
- VALGRIND_LOG="$LOG_DIR/valgrind-%p.log"
@@ -76,7 +76,7 @@ addons:
- valgrind
- xclip
homebrew:
- update: true
+ update: false
packages:
- ccache
- ninja
diff --git a/ci/common/build.sh b/ci/common/build.sh
index bdbe012ca6..8e9b2f8ebb 100644
--- a/ci/common/build.sh
+++ b/ci/common/build.sh
@@ -84,12 +84,11 @@ build_nvim() {
fi
# Invoke nvim to trigger *San early.
- if ! (bin/nvim --version && bin/nvim -u NONE -e -c ':qall') ; then
- asan_check "${LOG_DIR}"
+ if ! (bin/nvim --version && bin/nvim -u NONE -e -cq | cat -vet) ; then
+ check_sanitizer "${LOG_DIR}"
exit 1
fi
- asan_check "${LOG_DIR}"
-
+ check_sanitizer "${LOG_DIR}"
cd "${TRAVIS_BUILD_DIR}"
}
diff --git a/ci/common/test.sh b/ci/common/test.sh
index fb2dcc077e..0233d62c96 100644
--- a/ci/common/test.sh
+++ b/ci/common/test.sh
@@ -80,8 +80,8 @@ valgrind_check() {
check_logs "${1}" "valgrind-*"
}
-asan_check() {
- if test "${CLANG_SANITIZER}" = "ASAN_UBSAN" ; then
+check_sanitizer() {
+ if test -n "${CLANG_SANITIZER}"; then
check_logs "${1}" "*san.*"
fi
}
@@ -104,7 +104,7 @@ run_functionaltests() {(
fail 'functionaltests' F 'Functional tests failed'
fi
submit_coverage functionaltest
- asan_check "${LOG_DIR}"
+ check_sanitizer "${LOG_DIR}"
valgrind_check "${LOG_DIR}"
check_core_dumps
exit_suite
@@ -118,7 +118,7 @@ run_oldtests() {(
fail 'oldtests' F 'Legacy tests failed'
fi
submit_coverage oldtest
- asan_check "${LOG_DIR}"
+ check_sanitizer "${LOG_DIR}"
valgrind_check "${LOG_DIR}"
check_core_dumps
exit_suite
diff --git a/src/.tsan-suppressions b/src/.tsan-suppressions
new file mode 100644
index 0000000000..c004a468a6
--- /dev/null
+++ b/src/.tsan-suppressions
@@ -0,0 +1,2 @@
+# Ref: https://github.com/neovim/neovim/pull/10591#issuecomment-521248233
+race:starting
diff --git a/src/nvim/README.md b/src/nvim/README.md
index 3c956cb2e9..64d729cc8b 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -63,7 +63,7 @@ Enable the sanitizer(s) via these environment variables:
export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
export MSAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
- export TSAN_OPTIONS="external_symbolizer_path=/usr/lib/llvm-5.0/bin/llvm-symbolizer log_path=${HOME}/logs/tsan"
+ export TSAN_OPTIONS="log_path=${HOME}/logs/tsan:suppressions=${NVIM_PATH}/src/.tsan-suppressions"
Logs will be written to `${HOME}/logs/*san.PID`.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index fde84024b3..7e0a6c3329 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3842,26 +3842,24 @@ int ins_compl_add_tv(typval_T *const tv, const Direction dir)
(char_u **)cptext, true, dir, 0, adup, aequal);
}
-/*
- * Get the next expansion(s), using "compl_pattern".
- * The search starts at position "ini" in curbuf and in the direction
- * compl_direction.
- * When "compl_started" is FALSE start at that position, otherwise continue
- * where we stopped searching before.
- * This may return before finding all the matches.
- * Return the total number of matches or -1 if still unknown -- Acevedo
- */
+// Get the next expansion(s), using "compl_pattern".
+// The search starts at position "ini" in curbuf and in the direction
+// compl_direction.
+// When "compl_started" is FALSE start at that position, otherwise continue
+// where we stopped searching before.
+// This may return before finding all the matches.
+// Return the total number of matches or -1 if still unknown -- Acevedo
static int ins_compl_get_exp(pos_T *ini)
{
static pos_T first_match_pos;
static pos_T last_match_pos;
- static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */
- static int found_all = FALSE; /* Found all matches of a
- certain type. */
- static buf_T *ins_buf = NULL; /* buffer being scanned */
+ static char_u *e_cpt = (char_u *)""; // curr. entry in 'complete'
+ static int found_all = false; // Found all matches of a
+ // certain type.
+ static buf_T *ins_buf = NULL; // buffer being scanned
- pos_T *pos;
- char_u **matches;
+ pos_T *pos;
+ char_u **matches;
int save_p_scs;
bool save_p_ws;
int save_p_ic;
@@ -3870,12 +3868,14 @@ static int ins_compl_get_exp(pos_T *ini)
int len;
int found_new_match;
int type = ctrl_x_mode;
- char_u *ptr;
- char_u *dict = NULL;
+ char_u *ptr;
+ char_u *dict = NULL;
int dict_f = 0;
int set_match_pos;
int l_ctrl_x_mode = ctrl_x_mode;
+ assert(curbuf != NULL);
+
if (!compl_started) {
FOR_ALL_BUFFERS(buf) {
buf->b_scanned = false;
@@ -3899,9 +3899,9 @@ static int ins_compl_get_exp(pos_T *ini)
assert(l_ctrl_x_mode == ctrl_x_mode);
- /* For ^N/^P pick a new entry from e_cpt if compl_started is off,
- * or if found_all says this entry is done. For ^X^L only use the
- * entries from 'complete' that look in loaded buffers. */
+ // For ^N/^P pick a new entry from e_cpt if compl_started is off,
+ // or if found_all says this entry is done. For ^X^L only use the
+ // entries from 'complete' that look in loaded buffers.
if ((l_ctrl_x_mode == CTRL_X_NORMAL
|| CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode))
&& (!compl_started || found_all)) {
@@ -3923,23 +3923,24 @@ static int ins_compl_get_exp(pos_T *ini)
last_match_pos = first_match_pos;
type = 0;
- /* Remember the first match so that the loop stops when we
- * wrap and come back there a second time. */
- set_match_pos = TRUE;
+ // Remember the first match so that the loop stops when we
+ // wrap and come back there a second time.
+ set_match_pos = true;
} else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
&& (ins_buf =
- ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf) {
- /* Scan a buffer, but not the current one. */
- if (ins_buf->b_ml.ml_mfp != NULL) { /* loaded buffer */
- compl_started = TRUE;
+ ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf) {
+ // Scan a buffer, but not the current one.
+ if (ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
+ compl_started = true;
first_match_pos.col = last_match_pos.col = 0;
first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
last_match_pos.lnum = 0;
type = 0;
- } else { /* unloaded buffer, scan like dictionary */
- found_all = TRUE;
- if (ins_buf->b_fname == NULL)
+ } else { // unloaded buffer, scan like dictionary
+ found_all = true;
+ if (ins_buf->b_fname == NULL) {
continue;
+ }
type = CTRL_X_DICTIONARY;
dict = ins_buf->b_fname;
dict_f = DICT_EXACT;
@@ -3977,7 +3978,7 @@ static int ins_compl_get_exp(pos_T *ini)
type = -1;
}
- /* in any case e_cpt is advanced to the next entry */
+ // in any case e_cpt is advanced to the next entry
(void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
found_all = TRUE;
@@ -4024,12 +4025,12 @@ static int ins_compl_get_exp(pos_T *ini)
break;
case CTRL_X_TAGS:
- /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
+ // set p_ic according to p_ic, p_scs and pat for find_tags().
save_p_ic = p_ic;
p_ic = ignorecase(compl_pattern);
- /* Find up to TAG_MANY matches. Avoids that an enormous number
- * of matches is found when compl_pattern is empty */
+ // Find up to TAG_MANY matches. Avoids that an enormous number
+ // of matches is found when compl_pattern is empty
if (find_tags(compl_pattern, &num_matches, &matches,
TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
| (l_ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
@@ -4041,9 +4042,8 @@ static int ins_compl_get_exp(pos_T *ini)
case CTRL_X_FILES:
if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
- EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) {
-
- /* May change home directory back to "~". */
+ EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) {
+ // May change home directory back to "~".
tilde_replace(compl_pattern, num_matches, matches);
ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
}
@@ -4068,19 +4068,17 @@ static int ins_compl_get_exp(pos_T *ini)
ins_compl_add_matches(num_matches, matches, p_ic);
break;
- default: /* normal ^P/^N and ^X^L */
- /*
- * If 'infercase' is set, don't use 'smartcase' here
- */
+ default: // normal ^P/^N and ^X^L
+ // If 'infercase' is set, don't use 'smartcase' here
save_p_scs = p_scs;
assert(ins_buf);
if (ins_buf->b_p_inf)
p_scs = FALSE;
- /* Buffers other than curbuf are scanned from the beginning or the
- * end but never from the middle, thus setting nowrapscan in this
- * buffers is a good idea, on the other hand, we always set
- * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
+ // Buffers other than curbuf are scanned from the beginning or the
+ // end but never from the middle, thus setting nowrapscan in this
+ // buffers is a good idea, on the other hand, we always set
+ // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
save_p_ws = p_ws;
if (ins_buf != curbuf)
p_ws = false;
@@ -4089,8 +4087,7 @@ static int ins_compl_get_exp(pos_T *ini)
for (;; ) {
int flags = 0;
- ++msg_silent; /* Don't want messages for wrapscan. */
-
+ msg_silent++; // Don't want messages for wrapscan.
// CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode) || word-wise search that
// has added a word that was at the beginning of the line.
if (CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode)
@@ -4107,47 +4104,52 @@ static int ins_compl_get_exp(pos_T *ini)
}
msg_silent--;
if (!compl_started || set_match_pos) {
- /* set "compl_started" even on fail */
- compl_started = TRUE;
+ // set "compl_started" even on fail
+ compl_started = true;
first_match_pos = *pos;
last_match_pos = *pos;
- set_match_pos = FALSE;
+ set_match_pos = false;
} else if (first_match_pos.lnum == last_match_pos.lnum
- && first_match_pos.col == last_match_pos.col)
+ && first_match_pos.col == last_match_pos.col) {
found_new_match = FAIL;
+ }
if (found_new_match == FAIL) {
if (ins_buf == curbuf)
found_all = TRUE;
break;
}
- /* when ADDING, the text before the cursor matches, skip it */
- if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf
- && ini->lnum == pos->lnum
- && ini->col == pos->col)
+ // when ADDING, the text before the cursor matches, skip it
+ if ((compl_cont_status & CONT_ADDING) && ins_buf == curbuf
+ && ini->lnum == pos->lnum
+ && ini->col == pos->col) {
continue;
- ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
+ }
+ ptr = ml_get_buf(ins_buf, pos->lnum, false) + pos->col;
if (CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode)) {
if (compl_cont_status & CONT_ADDING) {
- if (pos->lnum >= ins_buf->b_ml.ml_line_count)
+ if (pos->lnum >= ins_buf->b_ml.ml_line_count) {
continue;
- ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
- if (!p_paste)
+ }
+ ptr = ml_get_buf(ins_buf, pos->lnum + 1, false);
+ if (!p_paste) {
ptr = skipwhite(ptr);
+ }
}
len = (int)STRLEN(ptr);
} else {
- char_u *tmp_ptr = ptr;
+ char_u *tmp_ptr = ptr;
if (compl_cont_status & CONT_ADDING) {
tmp_ptr += compl_length;
- /* Skip if already inside a word. */
- if (vim_iswordp(tmp_ptr))
+ // Skip if already inside a word.
+ if (vim_iswordp(tmp_ptr)) {
continue;
- /* Find start of next word. */
+ }
+ // Find start of next word.
tmp_ptr = find_word_start(tmp_ptr);
}
- /* Find end of this word. */
+ // Find end of this word.
tmp_ptr = find_word_end(tmp_ptr);
len = (int)(tmp_ptr - ptr);
@@ -4160,15 +4162,16 @@ static int ins_compl_get_exp(pos_T *ini)
STRNCPY(IObuff, ptr, len);
ptr = ml_get_buf(ins_buf, pos->lnum + 1, false);
tmp_ptr = ptr = skipwhite(ptr);
- /* Find start of next word. */
+ // Find start of next word.
tmp_ptr = find_word_start(tmp_ptr);
- /* Find end of next word. */
+ // Find end of next word.
tmp_ptr = find_word_end(tmp_ptr);
if (tmp_ptr > ptr) {
if (*ptr != ')' && IObuff[len - 1] != TAB) {
- if (IObuff[len - 1] != ' ')
+ if (IObuff[len - 1] != ' ') {
IObuff[len++] = ' ';
- /* IObuf =~ "\k.* ", thus len >= 2 */
+ }
+ // IObuf =~ "\k.* ", thus len >= 2
if (p_js
&& (IObuff[len - 2] == '.'
|| IObuff[len - 2] == '?'
@@ -4176,9 +4179,10 @@ static int ins_compl_get_exp(pos_T *ini)
IObuff[len++] = ' ';
}
}
- /* copy as much as possible of the new word */
- if (tmp_ptr - ptr >= IOSIZE - len)
+ // copy as much as possible of the new word
+ if (tmp_ptr - ptr >= IOSIZE - len) {
tmp_ptr = ptr + IOSIZE - len - 1;
+ }
STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
len += (int)(tmp_ptr - ptr);
flags |= CONT_S_IPOS;
@@ -4214,9 +4218,10 @@ static int ins_compl_get_exp(pos_T *ini)
|| found_new_match != FAIL) {
if (got_int)
break;
- /* Fill the popup menu as soon as possible. */
- if (type != -1)
+ // Fill the popup menu as soon as possible.
+ if (type != -1) {
ins_compl_check_keys(0, false);
+ }
if ((l_ctrl_x_mode != CTRL_X_NORMAL
&& !CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode))
@@ -4225,7 +4230,7 @@ static int ins_compl_get_exp(pos_T *ini)
}
compl_started = TRUE;
} else {
- /* Mark a buffer scanned when it has been scanned completely */
+ // Mark a buffer scanned when it has been scanned completely
if (type == 0 || type == CTRL_X_PATH_PATTERNS) {
assert(ins_buf);
ins_buf->b_scanned = true;
@@ -4242,7 +4247,7 @@ static int ins_compl_get_exp(pos_T *ini)
found_new_match = FAIL;
}
- i = -1; /* total of matches, unknown */
+ i = -1; // total of matches, unknown
if (found_new_match == FAIL
|| (l_ctrl_x_mode != CTRL_X_NORMAL
&& !CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode))) {
@@ -4263,7 +4268,7 @@ static int ins_compl_get_exp(pos_T *ini)
return i;
}
-/* Delete the old text being completed. */
+// Delete the old text being completed.
static void ins_compl_delete(void)
{
int col;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a3a66a5764..6703d15be0 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -13640,10 +13640,6 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- if (p_pyx == 0) {
- p_pyx = 2;
- }
-
script_host_eval("python", argvars, rettv);
}
@@ -13652,10 +13648,6 @@ static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- if (p_pyx == 0) {
- p_pyx = 3;
- }
-
script_host_eval("python3", argvars, rettv);
}
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 408c6dce79..df23d0630a 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2830,9 +2830,9 @@ void ex_options(exarg_T *eap)
void init_pyxversion(void)
{
if (p_pyx == 0) {
- if (!eval_has_provider("python3")) {
+ if (eval_has_provider("python3")) {
p_pyx = 3;
- } else if (!eval_has_provider("python")) {
+ } else if (eval_has_provider("python")) {
p_pyx = 2;
}
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 99ccce1793..1b2143c419 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -4375,7 +4375,7 @@ static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol,
screen_adjust_grid(&grid, &row, &coloff);
// Safety check. Avoids clang warnings down the call stack.
- if (grid->chars == NULL || row >= grid->Rows || col >= grid->Columns) {
+ if (grid->chars == NULL || row >= grid->Rows || coloff >= grid->Columns) {
DLOG("invalid state, skipped");
return;
}
diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh
index 43556f3ad3..249b89d04e 100755
--- a/src/nvim/testdir/runnvim.sh
+++ b/src/nvim/testdir/runnvim.sh
@@ -64,7 +64,7 @@ main() {(
fi
valgrind_check .
if test -n "$LOG_DIR" ; then
- asan_check "$LOG_DIR"
+ check_sanitizer "$LOG_DIR"
fi
check_core_dumps
if test "$FAILED" = 1 ; then
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 2cb3cf7ee7..9517b362af 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -480,8 +480,26 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
if (curgrid != &default_grid) {
flags = flags & ~kLineFlagWrap;
}
- assert(row < default_grid.Rows);
- assert(clearcol <= default_grid.Columns);
+
+ assert(endcol <= clearcol);
+
+ // TODO(bfredl): this should not really be necessary. But on some condition
+ // when resizing nvim, a window will be attempted to be drawn on the older
+ // and possibly larger global screen size.
+ if (row >= default_grid.Rows) {
+ DLOG("compositor: invalid row %"PRId64" on grid %"PRId64, row, grid);
+ return;
+ }
+ if (clearcol > default_grid.Columns) {
+ DLOG("compositor: invalid last column %"PRId64" on grid %"PRId64,
+ clearcol, grid);
+ if (startcol >= default_grid.Columns) {
+ return;
+ }
+ clearcol = default_grid.Columns;
+ endcol = MIN(endcol, clearcol);
+ }
+
if (flags & kLineFlagInvalid
|| kv_size(layers) > curgrid->comp_index+1
|| curgrid->blending) {
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index 68d4d1e2a1..a3c6c57a73 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -90,6 +90,12 @@ describe('python3 provider', function()
eq({1, 2, {['key'] = 'val'}}, eval([[py3eval('[1, 2, {"key": "val"}]')]]))
end)
+ it('pyxeval #10758', function()
+ eq(0, eval([[&pyxversion]]))
+ eq(3, eval([[pyxeval('sys.version_info[:3][0]')]]))
+ eq(3, eval([[&pyxversion]]))
+ end)
+
it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function()
source([=[
python3 << EOF