]> granicus.if.org Git - vim/commitdiff
updated for version 7.4.560 v7.4.560
authorBram Moolenaar <Bram@vim.org>
Wed, 17 Dec 2014 20:00:49 +0000 (21:00 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 17 Dec 2014 20:00:49 +0000 (21:00 +0100)
Problem:    Memory leak using :wviminfo. Issue 296.
Solution:   Free memory when needed. (idea by Christian Brabandt)

src/ops.c
src/version.c

index 0db8c2d25ca6c60c358a58632243ed07cddac8a9..0c3d11b87ff79f1fdf5d7a818cdb090eb1066c83 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -5663,6 +5663,8 @@ read_viminfo_register(virp, force)
     int                set_prev = FALSE;
     char_u     *str;
     char_u     **array = NULL;
+    int                new_type;
+    colnr_T    new_width;
 
     /* We only get here (hopefully) if line[0] == '"' */
     str = virp->vir_line + 1;
@@ -5695,21 +5697,25 @@ read_viminfo_register(virp, force)
     limit = 100;       /* Optimized for registers containing <= 100 lines */
     if (do_it)
     {
+       /*
+        * Build the new register in array[].
+        * y_array is kept as-is until done.
+        * The "do_it" flag is reset when something is wrong, in which case
+        * array[] needs to be freed.
+        */
        if (set_prev)
            y_previous = y_current;
-       vim_free(y_current->y_array);
-       array = y_current->y_array =
-                      (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
+       array = (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
        str = skipwhite(skiptowhite(str));
        if (STRNCMP(str, "CHAR", 4) == 0)
-           y_current->y_type = MCHAR;
+           new_type = MCHAR;
        else if (STRNCMP(str, "BLOCK", 5) == 0)
-           y_current->y_type = MBLOCK;
+           new_type = MBLOCK;
        else
-           y_current->y_type = MLINE;
+           new_type = MLINE;
        /* get the block width; if it's missing we get a zero, which is OK */
        str = skipwhite(skiptowhite(str));
-       y_current->y_width = getdigits(&str);
+       new_width = getdigits(&str);
     }
 
     while (!(eof = viminfo_readline(virp))
@@ -5717,40 +5723,66 @@ read_viminfo_register(virp, force)
     {
        if (do_it)
        {
-           if (size >= limit)
+           if (size == limit)
            {
-               y_current->y_array = (char_u **)
+               char_u **new_array = (char_u **)
                              alloc((unsigned)(limit * 2 * sizeof(char_u *)));
+
+               if (new_array == NULL)
+               {
+                   do_it = FALSE;
+                   break;
+               }
                for (i = 0; i < limit; i++)
-                   y_current->y_array[i] = array[i];
+                   new_array[i] = array[i];
                vim_free(array);
+               array = new_array;
                limit *= 2;
-               array = y_current->y_array;
            }
            str = viminfo_readstring(virp, 1, TRUE);
            if (str != NULL)
                array[size++] = str;
            else
+               /* error, don't store the result */
                do_it = FALSE;
        }
     }
     if (do_it)
     {
+       /* free y_array[] */
+       for (i = 0; i < y_current->y_size; i++)
+           vim_free(y_current->y_array[i]);
+       vim_free(y_current->y_array);
+
+       y_current->y_type = new_type;
+       y_current->y_width = new_width;
+       y_current->y_size = size;
        if (size == 0)
        {
-           vim_free(array);
            y_current->y_array = NULL;
        }
-       else if (size < limit)
+       else
        {
+           /* Move the lines from array[] to y_array[]. */
            y_current->y_array =
                        (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
            for (i = 0; i < size; i++)
-               y_current->y_array[i] = array[i];
-           vim_free(array);
+           {
+               if (y_current->y_array == NULL)
+                   vim_free(array[i]);
+               else
+                   y_current->y_array[i] = array[i];
+           }
        }
-       y_current->y_size = size;
     }
+    else
+    {
+       /* Free array[] if it was filled. */
+       for (i = 0; i < size; i++)
+           vim_free(array[i]);
+    }
+    vim_free(array);
+
     return eof;
 }
 
index e2ac04052e66a90f3892c40821574fcc98f6f07f..2ca9502d147cf0612e0e7f2d56f22edf0c8cb0b1 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    560,
 /**/
     559,
 /**/