@@ -899,7 +899,12 @@ static char *path_lookup(const char *cmd, char **path, int exe_only)
899899 return prog ;
900900}
901901
902- static char * * do_putenv (char * * env , const char * name , int free_old );
902+ static int do_putenv (char * * env , const char * name , int size , int free_old );
903+
904+ /* used number of elements of environ array, including terminating NULL */
905+ static int environ_size = 0 ;
906+ /* allocated size of environ array, in bytes */
907+ static int environ_alloc = 0 ;
903908
904909static int compareenv (const void * a , const void * b )
905910{
@@ -915,31 +920,28 @@ static int compareenv(const void *a, const void *b)
915920static wchar_t * make_environment_block (char * * deltaenv )
916921{
917922 wchar_t * wenvblk = NULL ;
918- int count = 0 ;
919- char * * e , * * tmpenv ;
920- int size = 0 , wenvsz = 0 , wenvpos = 0 ;
923+ char * * tmpenv ;
924+ int i = 0 , size = environ_size , wenvsz = 0 , wenvpos = 0 ;
921925
922- while (environ [ count ])
923- count ++ ;
926+ while (deltaenv && deltaenv [ i ])
927+ i ++ ;
924928
925- /* copy the environment */
926- tmpenv = xmalloc (sizeof ( * tmpenv ) * ( count + 1 ));
927- memcpy (tmpenv , environ , sizeof ( * tmpenv ) * ( count + 1 ));
929+ /* copy the environment, leaving space for changes */
930+ tmpenv = xmalloc (( size + i ) * sizeof ( char * ));
931+ memcpy (tmpenv , environ , size * sizeof ( char * ));
928932
929933 /* merge supplied environment changes into the temporary environment */
930- for (e = deltaenv ; e && * e ; e ++ )
931- tmpenv = do_putenv (tmpenv , * e , 0 );
934+ for (i = 0 ; deltaenv && deltaenv [ i ]; i ++ )
935+ size = do_putenv (tmpenv , deltaenv [ i ], size , 0 );
932936
933937 /* environment must be sorted */
934- for (count = 0 ; tmpenv [count ]; )
935- count ++ ;
936- qsort (tmpenv , count , sizeof (* tmpenv ), compareenv );
938+ qsort (tmpenv , size - 1 , sizeof (char * ), compareenv );
937939
938940 /* create environment block from temporary environment */
939- for (e = tmpenv ; * e ; e ++ ) {
940- size = 2 * strlen (* e ) + 2 ; /* +2 for final \0 */
941+ for (i = 0 ; tmpenv [ i ]; i ++ ) {
942+ size = 2 * strlen (tmpenv [ i ] ) + 2 ; /* +2 for final \0 */
941943 ALLOC_GROW (wenvblk , (wenvpos + size ) * sizeof (wchar_t ), wenvsz );
942- wenvpos += xutftowcs (& wenvblk [wenvpos ], * e , size ) + 1 ;
944+ wenvpos += xutftowcs (& wenvblk [wenvpos ], tmpenv [ i ] , size ) + 1 ;
943945 }
944946 /* add final \0 terminator */
945947 wenvblk [wenvpos ] = 0 ;
@@ -1206,31 +1208,33 @@ static int lookupenv(char **env, const char *name, size_t nmln)
12061208
12071209/*
12081210 * If name contains '=', then sets the variable, otherwise it unsets it
1211+ * Size includes the terminating NULL. Env must have room for size + 1 entries
1212+ * (in case of insert). Returns the new size. Optionally frees removed entries.
12091213 */
1210- static char * * do_putenv (char * * env , const char * name , int free_old )
1214+ static int do_putenv (char * * env , const char * name , int size , int free_old )
12111215{
12121216 char * eq = strchrnul (name , '=' );
12131217 int i = lookupenv (env , name , eq - name );
12141218
12151219 if (i < 0 ) {
12161220 if (* eq ) {
1217- for (i = 0 ; env [i ]; i ++ )
1218- ;
1219- env = xrealloc (env , (i + 2 )* sizeof (* env ));
1220- env [i ] = (char * ) name ;
1221- env [i + 1 ] = NULL ;
1221+ env [size - 1 ] = (char * ) name ;
1222+ env [size ] = NULL ;
1223+ size ++ ;
12221224 }
12231225 }
12241226 else {
12251227 if (free_old )
12261228 free (env [i ]);
12271229 if (* eq )
12281230 env [i ] = (char * ) name ;
1229- else
1231+ else {
12301232 for (; env [i ]; i ++ )
12311233 env [i ] = env [i + 1 ];
1234+ size -- ;
1235+ }
12321236 }
1233- return env ;
1237+ return size ;
12341238}
12351239
12361240#undef getenv
@@ -1248,7 +1252,8 @@ char *mingw_getenv(const char *name)
12481252
12491253int mingw_putenv (const char * namevalue )
12501254{
1251- environ = do_putenv (environ , namevalue , 1 );
1255+ ALLOC_GROW (environ , (environ_size + 1 ) * sizeof (char * ), environ_alloc );
1256+ environ_size = do_putenv (environ , namevalue , environ_size , 1 );
12521257 return 0 ;
12531258}
12541259
@@ -2048,7 +2053,9 @@ void mingw_startup()
20482053 maxlen = max (maxlen , wcslen (wenv [i ]));
20492054
20502055 /* nedmalloc can't free CRT memory, allocate resizable environment list */
2051- environ = xcalloc (i + 1 , sizeof (char * ));
2056+ environ = NULL ;
2057+ environ_size = i + 1 ;
2058+ ALLOC_GROW (environ , environ_size * sizeof (char * ), environ_alloc );
20522059
20532060 /* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
20542061 maxlen = 3 * maxlen + 1 ;
@@ -2065,6 +2072,7 @@ void mingw_startup()
20652072 len = xwcstoutf (buffer , wenv [i ], maxlen );
20662073 environ [i ] = xmemdupz (buffer , len );
20672074 }
2075+ environ [i ] = NULL ;
20682076 free (buffer );
20692077
20702078 /* initialize critical section for waitpid pinfo_t list */
0 commit comments