4141
4242static void set_options_default (int opt_flags );
4343static void set_string_default_esc (char * name , char_u * val , int escape );
44- static char_u * find_dup_item (char_u * origval , char_u * newval , long_u flags );
44+ static char_u * find_dup_item (char_u * origval , char_u * newval , size_t newvallen , long_u flags );
4545static char_u * option_expand (int opt_idx , char_u * val );
4646static void didset_options (void );
4747static void didset_options2 (void );
@@ -132,51 +132,72 @@ set_init_default_shell(void)
132132set_init_default_backupskip (void )
133133{
134134 int opt_idx ;
135- long_u n ;
135+ int i ;
136136 char_u * p ;
137+ int plen ;
137138#ifdef UNIX
138139 static char * (names [4 ]) = {"" , "TMPDIR" , "TEMP" , "TMP" };
139140#else
140141 static char * (names [3 ]) = {"TMPDIR" , "TEMP" , "TMP" };
141142#endif
142- int len ;
143143 garray_T ga ;
144- char_u * item ;
145144
146145 opt_idx = findoption ((char_u * )"backupskip" );
147146
148147 ga_init2 (& ga , 1 , 100 );
149- for (n = 0 ; n < (long )ARRAY_LENGTH (names ); ++ n )
148+ for (i = 0 ; i < (int )ARRAY_LENGTH (names ); ++ i )
150149 {
151150 int mustfree = FALSE;
152151#ifdef UNIX
153- if (* names [n ] == NUL )
152+ if (* names [i ] == NUL )
153+ {
154154# ifdef MACOS_X
155155 p = (char_u * )"/private/tmp" ;
156+ plen = (int )STRLEN_LITERAL ("/private/tmp" );
156157# else
157- p = (char_u * )"/tmp" ;
158+ p = (char_u * )"/tmp" ;
159+ plen = (int )STRLEN_LITERAL ("/tmp" );
158160# endif
161+ }
159162 else
160163#endif
161- p = vim_getenv ((char_u * )names [n ], & mustfree );
164+ {
165+ p = vim_getenv ((char_u * )names [i ], & mustfree );
166+ plen = 0 ; // will be calculated below
167+ }
162168 if (p != NULL && * p != NUL )
163169 {
164- // First time count the NUL, otherwise count the ','.
165- len = (int )STRLEN (p ) + 3 ;
166- item = alloc (len );
170+ char_u * item ;
171+ size_t itemsize ;
172+ int has_trailing_path_sep = FALSE;
173+
174+ if (plen == 0 )
175+ {
176+ // the value was retrieved from the environment
177+ plen = (int )STRLEN (p );
178+ // does the value include a trailing path separator?
179+ if (after_pathsep (p , p + plen ))
180+ has_trailing_path_sep = TRUE;
181+ }
182+
183+ // item size needs to be large enough to include "/*" and a trailing NUL
184+ // note: the value (and therefore plen) may already include a path separator
185+ itemsize = plen + (has_trailing_path_sep ? 0 : 1 ) + 2 ;
186+ item = alloc (itemsize );
167187 if (item != NULL )
168188 {
169- STRCPY (item , p );
170- add_pathsep (item );
171- STRCAT (item , "*" );
172- if (find_dup_item (ga .ga_data , item , options [opt_idx ].flags )
173- == NULL
174- && ga_grow (& ga , len ) == OK )
189+ // add a preceeding comma as a separator after the first item
190+ size_t itemseplen = (ga .ga_len == 0 ) ? 0 : 1 ;
191+ size_t itemlen ;
192+
193+ itemlen = vim_snprintf ((char * )item , itemsize , "%s%s*" , p , (has_trailing_path_sep ) ? "" : PATHSEPSTR );
194+
195+ if (find_dup_item (ga .ga_data , item , itemlen , options [opt_idx ].flags ) == NULL
196+ && ga_grow (& ga , itemseplen + itemlen + 1 ) == OK )
175197 {
176- if (ga .ga_len > 0 )
177- STRCAT (ga .ga_data , "," );
178- STRCAT (ga .ga_data , item );
179- ga .ga_len += len ;
198+ ga .ga_len += vim_snprintf ((char * )ga .ga_data + ga .ga_len ,
199+ itemseplen + itemlen + 1 ,
200+ "%s%s" , (itemseplen > 0 ) ? "," : "" , item );
180201 }
181202 vim_free (item );
182203 }
@@ -524,7 +545,7 @@ set_init_default_encoding(void)
524545 // MS-Windows has builtin support for conversion to and from Unicode, using
525546 // "utf-8" for 'encoding' should work best for most users.
526547 // z/OS built should default to UTF-8 mode as setlocale does not respect utf-8 environment variable locales
527- p = vim_strsave ((char_u * )ENC_DFLT );
548+ p = vim_strnsave ((char_u * )ENC_DFLT , STRLEN_LITERAL ( ENC_DFLT ) );
528549# else
529550 // enc_locale() will try to find the encoding of the current locale.
530551 // This works best for properly configured systems, old and new.
@@ -542,7 +563,7 @@ set_init_default_encoding(void)
542563 // We don't support "gb18030", but "cp936" is a good substitute
543564 // for practical purposes, thus use that. It's not an alias to
544565 // still support conversion between gb18030 and utf-8.
545- p_enc = vim_strsave ((char_u * )"cp936" );
566+ p_enc = vim_strnsave ((char_u * )"cp936" , STRLEN_LITERAL ( "cp936" ) );
546567 vim_free (p );
547568 }
548569 if (mb_init () == NULL )
@@ -584,14 +605,15 @@ set_init_default_encoding(void)
584605 GetACP () != GetConsoleCP ())
585606 {
586607 char buf [50 ];
608+ size_t buflen ;
587609
588610 // Win32 console: In ConPTY, GetConsoleCP() returns zero.
589611 // Use an alternative value.
590612 if (GetConsoleCP () == 0 )
591- sprintf (buf , "cp%ld" , (long )GetACP ());
613+ buflen = vim_snprintf (buf , sizeof ( buf ) , "cp%ld" , (long )GetACP ());
592614 else
593- sprintf (buf , "cp%ld" , (long )GetConsoleCP ());
594- p_tenc = vim_strsave ((char_u * )buf );
615+ buflen = vim_snprintf (buf , sizeof ( buf ) , "cp%ld" , (long )GetConsoleCP ());
616+ p_tenc = vim_strnsave ((char_u * )buf , buflen );
595617 if (p_tenc != NULL )
596618 {
597619 opt_idx = findoption ((char_u * )"termencoding" );
@@ -885,25 +907,23 @@ set_string_default(char *name, char_u *val)
885907 * "origval". Return NULL if not found.
886908 */
887909 static char_u *
888- find_dup_item (char_u * origval , char_u * newval , long_u flags )
910+ find_dup_item (char_u * origval , char_u * newval , size_t newvallen , long_u flags )
889911{
890912 int bs = 0 ;
891- size_t newlen ;
892913 char_u * s ;
893914
894915 if (origval == NULL )
895916 return NULL ;
896917
897- newlen = STRLEN (newval );
898918 for (s = origval ; * s != NUL ; ++ s )
899919 {
900920 if ((!(flags & P_COMMA )
901921 || s == origval
902922 || (s [-1 ] == ',' && !(bs & 1 )))
903- && STRNCMP (s , newval , newlen ) == 0
923+ && STRNCMP (s , newval , newvallen ) == 0
904924 && (!(flags & P_COMMA )
905- || s [newlen ] == ','
906- || s [newlen ] == NUL ))
925+ || s [newvallen ] == ','
926+ || s [newvallen ] == NUL ))
907927 return s ;
908928 // Count backslashes. Only a comma with an even number of backslashes
909929 // or a single backslash preceded by a comma before it is recognized as
@@ -1289,28 +1309,34 @@ set_init_3(void)
12891309set_helplang_default (char_u * lang )
12901310{
12911311 int idx ;
1312+ size_t langlen ;
12921313
1293- if (lang == NULL || STRLEN ( lang ) < 2 ) // safety check
1314+ if (lang == NULL ) // safety check
12941315 return ;
1316+
1317+ langlen = STRLEN (lang );
1318+ if (langlen < 2 ) // safety check
1319+ return ;
1320+
12951321 idx = findoption ((char_u * )"hlg" );
12961322 if (idx < 0 || (options [idx ].flags & P_WAS_SET ))
12971323 return ;
12981324
12991325 if (options [idx ].flags & P_ALLOCED )
13001326 free_string_option (p_hlg );
1301- p_hlg = vim_strsave (lang );
1327+ p_hlg = vim_strnsave (lang , langlen );
13021328 if (p_hlg == NULL )
13031329 p_hlg = empty_option ;
13041330 else
13051331 {
13061332 // zh_CN becomes "cn", zh_TW becomes "tw"
1307- if (STRNICMP (p_hlg , "zh_" , 3 ) == 0 && STRLEN ( p_hlg ) >= 5 )
1333+ if (STRNICMP (p_hlg , "zh_" , 3 ) == 0 && langlen >= 5 )
13081334 {
13091335 p_hlg [0 ] = TOLOWER_ASC (p_hlg [3 ]);
13101336 p_hlg [1 ] = TOLOWER_ASC (p_hlg [4 ]);
13111337 }
13121338 // any C like setting, such as C.UTF-8, becomes "en"
1313- else if (STRLEN ( p_hlg ) >= 1 && * p_hlg == 'C' )
1339+ else if (langlen >= 1 && * p_hlg == 'C' )
13141340 {
13151341 p_hlg [0 ] = 'e' ;
13161342 p_hlg [1 ] = 'n' ;
@@ -1625,13 +1651,13 @@ opt_backspace_nr2str(
16251651 * (char_u * * )varp = empty_option ;
16261652 break ;
16271653 case 1 :
1628- * (char_u * * )varp = vim_strsave ((char_u * )"indent,eol" );
1654+ * (char_u * * )varp = vim_strnsave ((char_u * )"indent,eol" , STRLEN_LITERAL ( "indent,eol" ) );
16291655 break ;
16301656 case 2 :
1631- * (char_u * * )varp = vim_strsave ((char_u * )"indent,eol,start" );
1657+ * (char_u * * )varp = vim_strnsave ((char_u * )"indent,eol,start" , STRLEN_LITERAL ( "indent,eol,start" ) );
16321658 break ;
16331659 case 3 :
1634- * (char_u * * )varp = vim_strsave ((char_u * )"indent,eol,nostop" );
1660+ * (char_u * * )varp = vim_strnsave ((char_u * )"indent,eol,nostop" , STRLEN_LITERAL ( "indent,eol,nostop" ) );
16351661 break ;
16361662 }
16371663 vim_free (* oldval_p );
@@ -1652,20 +1678,37 @@ opt_backspace_nr2str(
16521678 static char_u *
16531679opt_whichwrap_nr2str (char_u * * argp , char_u * whichwrap )
16541680{
1681+ size_t len = 0 ;
1682+
16551683 * whichwrap = NUL ;
16561684 int i = getdigits (argp );
16571685 if (i & 1 )
1658- STRCAT (whichwrap , "b," );
1686+ {
1687+ STRCPY (whichwrap , "b," );
1688+ len += 2 ;
1689+ }
16591690 if (i & 2 )
1660- STRCAT (whichwrap , "s," );
1691+ {
1692+ STRCPY (whichwrap + len , "s," );
1693+ len += 2 ;
1694+ }
16611695 if (i & 4 )
1662- STRCAT (whichwrap , "h,l," );
1696+ {
1697+ STRCPY (whichwrap + len , "h,l," );
1698+ len += 4 ;
1699+ }
16631700 if (i & 8 )
1664- STRCAT (whichwrap , "<,>," );
1701+ {
1702+ STRCPY (whichwrap + len , "<,>," );
1703+ len += 4 ;
1704+ }
16651705 if (i & 16 )
1666- STRCAT (whichwrap , "[,]," );
1706+ {
1707+ STRCPY (whichwrap + len , "[,]," );
1708+ len += 4 ;
1709+ }
16671710 if (* whichwrap != NUL ) // remove trailing ,
1668- whichwrap [STRLEN ( whichwrap ) - 1 ] = NUL ;
1711+ whichwrap [len - 1 ] = NUL ;
16691712
16701713 return whichwrap ;
16711714}
@@ -1952,7 +1995,7 @@ stropt_get_newval(
19521995 if (op == OP_REMOVING || (flags & P_NODUP ))
19531996 {
19541997 len = (int )STRLEN (newval );
1955- s = find_dup_item (origval , newval , flags );
1998+ s = find_dup_item (origval , newval , len , flags );
19561999
19572000 // do not add if already there
19582001 if ((op == OP_ADDING || op == OP_PREPENDING ) && s != NULL )
@@ -2680,12 +2723,11 @@ do_set(
26802723
26812724 if (errmsg != NULL )
26822725 {
2683- vim_strncpy (IObuff , (char_u * )_ (errmsg ), IOSIZE - 1 );
2684- i = (int )STRLEN (IObuff ) + 2 ;
2726+ i = vim_snprintf ((char * )IObuff , IOSIZE , "%s" , (char_u * )_ (errmsg )) + 2 ;
26852727 if (i + (arg - startarg ) < IOSIZE )
26862728 {
26872729 // append the argument with the error
2688- STRCAT (IObuff , ": " );
2730+ STRCPY (IObuff + i - 2 , ": " );
26892731 mch_memmove (IObuff + i , startarg , (arg - startarg ));
26902732 IObuff [i + (arg - startarg )] = NUL ;
26912733 }
@@ -5100,7 +5142,7 @@ get_option_value(
51005142 // never return the value of the crypt key
51015143 else if ((char_u * * )varp == & curbuf -> b_p_key
51025144 && * * (char_u * * )(varp ) != NUL )
5103- * stringval = vim_strsave ((char_u * )"*****" );
5145+ * stringval = vim_strnsave ((char_u * )"*****" , STRLEN_LITERAL ( "*****" ) );
51045146#endif
51055147 else
51065148 * stringval = vim_strsave (* (char_u * * )(varp ));
@@ -7334,6 +7376,7 @@ set_context_in_set_cmd(
73347376 char_u * s ;
73357377 int is_term_option = FALSE;
73367378 int key ;
7379+ char_u * argend ;
73377380
73387381 expand_option_flags = opt_flags ;
73397382
@@ -7343,7 +7386,8 @@ set_context_in_set_cmd(
73437386 xp -> xp_pattern = arg ;
73447387 return ;
73457388 }
7346- p = arg + STRLEN (arg ) - 1 ;
7389+ argend = arg + STRLEN (arg );
7390+ p = argend - 1 ;
73477391 if (* p == ' ' && * (p - 1 ) != '\\' )
73487392 {
73497393 xp -> xp_pattern = p + 1 ;
@@ -7560,7 +7604,7 @@ set_context_in_set_cmd(
75607604 // delimited by space.
75617605 if ((flags & P_EXPAND ) || (flags & P_COMMA ) || (flags & P_COLON ))
75627606 {
7563- for (p = arg + STRLEN ( arg ) - 1 ; p >= xp -> xp_pattern ; -- p )
7607+ for (p = argend - 1 ; p >= xp -> xp_pattern ; -- p )
75647608 {
75657609 // count number of backslashes before ' ' or ',' or ':'
75667610 if (* p == ' ' || * p == ',' ||
@@ -7587,7 +7631,7 @@ set_context_in_set_cmd(
75877631 // An option that is a list of single-character flags should always start
75887632 // at the end as we don't complete words.
75897633 if (flags & P_FLAGLIST )
7590- xp -> xp_pattern = arg + STRLEN ( arg ) ;
7634+ xp -> xp_pattern = argend ;
75917635
75927636 // Some options can either be using file/dir expansions, or custom value
75937637 // expansion depending on what the user typed. Unfortunately we have to
@@ -8106,7 +8150,7 @@ ExpandSettingSubtract(
81068150 int count = 0 ;
81078151 char_u * p ;
81088152
8109- p = vim_strsave (option_val );
8153+ p = vim_strnsave (option_val , num_flags );
81108154 if (p == NULL )
81118155 {
81128156 VIM_CLEAR (* matches );
0 commit comments