# HG changeset patch # User Christian Brabandt # Date 1459688406 -7200 # Node ID a2c27f6aaf3a2192d0e55b8fa04509e5095b7cd9 # Parent 7e6aa24c48d2d5d573d79ff2f3e90501c069459c commit https://github.com/vim/vim/commit/4afc7c5d4a73340831077a02bfe1f74935e7f4a1 Author: Bram Moolenaar 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) diff --git a/src/hardcopy.c b/src/hardcopy.c --- 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; } diff --git a/src/testdir/test_hardcopy.vim b/src/testdir/test_hardcopy.vim --- 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() diff --git a/src/version.c b/src/version.c --- 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,