diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-02-11 13:46:35 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2018-02-11 19:03:27 +0100 |
commit | abed6a0b1a71e54b143e98678f4daa6818b02f8d (patch) | |
tree | fed29c0808a3b0fe88d1e5c41f00b4d270b42554 | |
parent | 4b7f7be3018563905d55197b43707ebe4ca12e78 (diff) | |
download | rneovim-abed6a0b1a71e54b143e98678f4daa6818b02f8d.tar.gz rneovim-abed6a0b1a71e54b143e98678f4daa6818b02f8d.tar.bz2 rneovim-abed6a0b1a71e54b143e98678f4daa6818b02f8d.zip |
vim-patch:8.0.1475: invalid memory access in read_redo()
Problem: Invalid memory access in read_redo(). (gy741)
Solution: Convert the replacement character back from a negative number to
CR or NL. (hint by Dominique Pelle, closes vim/vim#2616)
https://github.com/vim/vim/commit/f12519dec88251305793f1651f558d16506b4be2
-rw-r--r-- | src/nvim/normal.c | 25 | ||||
-rw-r--r-- | src/nvim/ops.c | 13 | ||||
-rw-r--r-- | src/nvim/testdir/test_undo.vim | 7 | ||||
-rw-r--r-- | src/nvim/vim.h | 4 |
4 files changed, 38 insertions, 11 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index bca4a0f93e..0feac03e32 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1641,12 +1641,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) prep_redo(oap->regname, cap->count0, get_op_char(oap->op_type), get_extra_op_char(oap->op_type), oap->motion_force, cap->cmdchar, cap->nchar); - else if (cap->cmdchar != ':') + else if (cap->cmdchar != ':') { + int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL; + + // reverse what nv_replace() did + if (nchar == REPLACE_CR_NCHAR) { + nchar = CAR; + } else if (nchar == REPLACE_NL_NCHAR) { + nchar = NL; + } prep_redo(oap->regname, 0L, NUL, 'v', get_op_char(oap->op_type), get_extra_op_char(oap->op_type), - oap->op_type == OP_REPLACE - ? cap->nchar : NUL); + nchar); + } if (!redo_VIsual_busy) { redo_VIsual_mode = resel_VIsual_mode; redo_VIsual_vcol = resel_VIsual_vcol; @@ -5854,10 +5862,13 @@ static void nv_replace(cmdarg_T *cap) if (got_int) reset_VIsual(); if (had_ctrl_v) { - if (cap->nchar == '\r') - cap->nchar = -1; - else if (cap->nchar == '\n') - cap->nchar = -2; + // Use a special (negative) number to make a difference between a + // literal CR or NL and a line break. + if (cap->nchar == CAR) { + cap->nchar = REPLACE_CR_NCHAR; + } else if (cap->nchar == NL) { + cap->nchar = REPLACE_NL_NCHAR; + } } nv_operator(cap); return; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 665a102253..4d974f5760 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1629,13 +1629,18 @@ int op_replace(oparg_T *oap, int c) colnr_T oldlen; struct block_def bd; char_u *after_p = NULL; - int had_ctrl_v_cr = (c == -1 || c == -2); + int had_ctrl_v_cr = false; if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty) return OK; /* nothing to do */ - if (had_ctrl_v_cr) - c = (c == -1 ? '\r' : '\n'); + if (c == REPLACE_CR_NCHAR) { + had_ctrl_v_cr = true; + c = CAR; + } else if (c == REPLACE_NL_NCHAR) { + had_ctrl_v_cr = true; + c = NL; + } if (has_mbyte) mb_adjust_opend(oap); @@ -1713,7 +1718,7 @@ int op_replace(oparg_T *oap, int c) // insert pre-spaces memset(newp + bd.textcol, ' ', (size_t)bd.startspaces); // insert replacement chars CHECK FOR ALLOCATED SPACE - // -1/-2 is used for entering CR literally. + // REPLACE_CR_NCHAR/REPLACE_NL_NCHAR is used for entering CR literally. size_t after_p_len = 0; if (had_ctrl_v_cr || (c != '\r' && c != '\n')) { // strlen(newp) at this point diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim index f7d1d64ea3..3373258708 100644 --- a/src/nvim/testdir/test_undo.vim +++ b/src/nvim/testdir/test_undo.vim @@ -282,3 +282,10 @@ func Test_cmd_in_reg_undo() only! let @a='' endfunc + +func Test_redo_empty_line() + new + exe "norm\x16r\x160" + exe "norm." + bwipe! +endfunc diff --git a/src/nvim/vim.h b/src/nvim/vim.h index b932c2d0f8..0c13d331c8 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -313,4 +313,8 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() # define OPEN_CHR_FILES #endif +// Replacement for nchar used by nv_replace(). +#define REPLACE_CR_NCHAR -1 +#define REPLACE_NL_NCHAR -2 + #endif // NVIM_VIM_H |