changeset 8829:a2c27f6aaf3a v7.4.1702

commit https://github.com/vim/vim/commit/4afc7c5d4a73340831077a02bfe1f74935e7f4a1 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 3 14:56:52 2016 +0200 patch 7.4.1702 Problem: Using freed memory when parsing 'printoptions' fails. Solution: Save the old options and restore them in case of an error. (Dominique)
author Christian Brabandt <cb@256bit.org>
date Sun, 03 Apr 2016 15:00:06 +0200
parents 7e6aa24c48d2
children d15abeac22c6
files src/hardcopy.c src/testdir/test_hardcopy.vim src/version.c
diffstat 3 files changed, 36 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/hardcopy.c
+++ b/src/hardcopy.c
@@ -189,6 +189,8 @@ parse_list_options(
     option_table_T	*table,
     int			table_size)
 {
+    option_table_T *old_opts;
+    char_u	*ret = NULL;
     char_u	*stringp;
     char_u	*colonp;
     char_u	*commap;
@@ -196,8 +198,16 @@ parse_list_options(
     int		idx = 0;		/* init for GCC */
     int		len;
 
+    /* Save the old values, so that they can be restored in case of an error. */
+    old_opts = (option_table_T *)alloc(sizeof(option_table_T) * table_size);
+    if (old_opts == NULL)
+	return NULL;
+
     for (idx = 0; idx < table_size; ++idx)
+    {
+	old_opts[idx] = table[idx];
 	table[idx].present = FALSE;
+    }
 
     /*
      * Repeat for all comma separated parts.
@@ -207,7 +217,10 @@ parse_list_options(
     {
 	colonp = vim_strchr(stringp, ':');
 	if (colonp == NULL)
-	    return (char_u *)N_("E550: Missing colon");
+	{
+	    ret = (char_u *)N_("E550: Missing colon");
+	    break;
+	}
 	commap = vim_strchr(stringp, ',');
 	if (commap == NULL)
 	    commap = option_str + STRLEN(option_str);
@@ -219,15 +232,20 @@ parse_list_options(
 		break;
 
 	if (idx == table_size)
-	    return (char_u *)N_("E551: Illegal component");
-
+	{
+	    ret = (char_u *)N_("E551: Illegal component");
+	    break;
+	}
 	p = colonp + 1;
 	table[idx].present = TRUE;
 
 	if (table[idx].hasnum)
 	{
 	    if (!VIM_ISDIGIT(*p))
-		return (char_u *)N_("E552: digit expected");
+	    {
+		ret = (char_u *)N_("E552: digit expected");
+		break;
+	    }
 
 	    table[idx].number = getdigits(&p); /*advances p*/
 	}
@@ -240,7 +258,14 @@ parse_list_options(
 	    ++stringp;
     }
 
-    return NULL;
+    if (ret != NULL)
+    {
+	/* Restore old options in case of error */
+	for (idx = 0; idx < table_size; ++idx)
+	    table[idx] = old_opts[idx];
+    }
+    vim_free(old_opts);
+    return ret;
 }
 
 
--- a/src/testdir/test_hardcopy.vim
+++ b/src/testdir/test_hardcopy.vim
@@ -23,6 +23,10 @@ func Test_printoptions_parsing()
   set printoptions=formfeed:y
   set printoptions=
   set printoptions&
+
+  call assert_fails('set printoptions=paper', 'E550:')
+  call assert_fails('set printoptions=shredder:on', 'E551:')
+  call assert_fails('set printoptions=left:no', 'E552:')
 endfunc
 
 func Test_printmbfont_parsing()
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1702,
+/**/
     1701,
 /**/
     1700,