changeset 13202:2941a86f8aaa v8.0.1475

patch 8.0.1475: invalid memory access in read_redo() commit https://github.com/vim/vim/commit/f12519dec88251305793f1651f558d16506b4be2 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 6 22:52:49 2018 +0100 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 #2616)
author Christian Brabandt <cb@256bit.org>
date Tue, 06 Feb 2018 23:00:07 +0100
parents e57e06cfb76b
children eafbec5a9528
files src/normal.c src/ops.c src/testdir/test_undo.vim src/version.c src/vim.h
diffstat 5 files changed, 43 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/normal.c
+++ b/src/normal.c
@@ -1685,11 +1685,19 @@ do_pending_operator(cmdarg_T *cap, int o
 			    get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
 			    oap->motion_force, cap->cmdchar, cap->nchar);
 		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;
@@ -7023,10 +7031,12 @@ nv_replace(cmdarg_T *cap)
 	    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;
--- a/src/ops.c
+++ b/src/ops.c
@@ -2113,13 +2113,21 @@ op_replace(oparg_T *oap, int c)
     size_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;
+    }
 
 #ifdef FEAT_MBYTE
     if (has_mbyte)
@@ -2207,7 +2215,8 @@ op_replace(oparg_T *oap, int c)
 	    /* insert pre-spaces */
 	    vim_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. */
 	    if (had_ctrl_v_cr || (c != '\r' && c != '\n'))
 	    {
 #ifdef FEAT_MBYTE
@@ -6370,7 +6379,7 @@ write_viminfo_registers(FILE *fp)
 	     * |{bartype},{flags},{name},{type},
 	     *      {linecount},{width},{timestamp},"line1","line2"
 	     * flags: REG_PREVIOUS - register is y_previous
-	     *        REG_EXEC - used for @@
+	     *	      REG_EXEC - used for @@
 	     */
 	    if (y_previous == &y_regs[i])
 		flags |= REG_PREVIOUS;
--- a/src/testdir/test_undo.vim
+++ b/src/testdir/test_undo.vim
@@ -403,3 +403,10 @@ func Test_undo_0()
 
   bwipe!
 endfunc
+
+func Test_redo_empty_line()
+  new
+  exe "norm\x16r\x160"
+  exe "norm."
+  bwipe!
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1475,
+/**/
     1474,
 /**/
     1473,
--- a/src/vim.h
+++ b/src/vim.h
@@ -2515,4 +2515,8 @@ typedef enum {
 # endif
 #endif
 
+/* Replacement for nchar used by nv_replace(). */
+#define REPLACE_CR_NCHAR    -1
+#define REPLACE_NL_NCHAR    -2
+
 #endif /* VIM__H */