]> granicus.if.org Git - vim/commitdiff
patch 8.0.1475: invalid memory access in read_redo() v8.0.1475
authorBram Moolenaar <Bram@vim.org>
Tue, 6 Feb 2018 21:52:49 +0000 (22:52 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 6 Feb 2018 21:52:49 +0000 (22:52 +0100)
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)

src/normal.c
src/ops.c
src/testdir/test_undo.vim
src/version.c
src/vim.h

index 745a2f68ce7cfd7a525c7cec767b7c492a311c42..79e0b68aa8f8f407a2ea37dce4115de720337238 100644 (file)
@@ -1685,11 +1685,19 @@ do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank)
                            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;
index 83c36bda67e2ab69fc6f37d115527f7071da0dcd..1350d826413e788d2af115e241591148de9839c4 100644 (file)
--- 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;
index cc3cceb1ae95257e0b5d48686194f2eb06ad9288..c1b821e4e110a1e838186469cf9540c661623352 100644 (file)
@@ -403,3 +403,10 @@ func Test_undo_0()
 
   bwipe!
 endfunc
+
+func Test_redo_empty_line()
+  new
+  exe "norm\x16r\x160"
+  exe "norm."
+  bwipe!
+endfunc
index 350c83067891bb9a52bd03c2f6fa7b491017a67c..98a913297cc70592ca5cbdb564b7b3903e380cd2 100644 (file)
@@ -771,6 +771,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1475,
 /**/
     1474,
 /**/
index ad372351e5495ca55f19663e5e7808cc689ba5c3..bd8ac0872316f29c7ce5ab0cb6d80b2ba6c7efc7 100644 (file)
--- 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 */