@@ -899,7 +899,12 @@ static char *path_lookup(const char *cmd, char **path, int exe_only)
899
899
return prog ;
900
900
}
901
901
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 ;
903
908
904
909
static int compareenv (const void * a , const void * b )
905
910
{
@@ -915,31 +920,28 @@ static int compareenv(const void *a, const void *b)
915
920
static wchar_t * make_environment_block (char * * deltaenv )
916
921
{
917
922
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 ;
921
925
922
- while (environ [ count ])
923
- count ++ ;
926
+ while (deltaenv && deltaenv [ i ])
927
+ i ++ ;
924
928
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 * ));
928
932
929
933
/* 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 );
932
936
933
937
/* 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 );
937
939
938
940
/* 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 */
941
943
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 ;
943
945
}
944
946
/* add final \0 terminator */
945
947
wenvblk [wenvpos ] = 0 ;
@@ -1206,31 +1208,33 @@ static int lookupenv(char **env, const char *name, size_t nmln)
1206
1208
1207
1209
/*
1208
1210
* 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.
1209
1213
*/
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 )
1211
1215
{
1212
1216
char * eq = strchrnul (name , '=' );
1213
1217
int i = lookupenv (env , name , eq - name );
1214
1218
1215
1219
if (i < 0 ) {
1216
1220
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 ++ ;
1222
1224
}
1223
1225
}
1224
1226
else {
1225
1227
if (free_old )
1226
1228
free (env [i ]);
1227
1229
if (* eq )
1228
1230
env [i ] = (char * ) name ;
1229
- else
1231
+ else {
1230
1232
for (; env [i ]; i ++ )
1231
1233
env [i ] = env [i + 1 ];
1234
+ size -- ;
1235
+ }
1232
1236
}
1233
- return env ;
1237
+ return size ;
1234
1238
}
1235
1239
1236
1240
#undef getenv
@@ -1248,7 +1252,8 @@ char *mingw_getenv(const char *name)
1248
1252
1249
1253
int mingw_putenv (const char * namevalue )
1250
1254
{
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 );
1252
1257
return 0 ;
1253
1258
}
1254
1259
@@ -2048,7 +2053,9 @@ void mingw_startup()
2048
2053
maxlen = max (maxlen , wcslen (wenv [i ]));
2049
2054
2050
2055
/* 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 );
2052
2059
2053
2060
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
2054
2061
maxlen = 3 * maxlen + 1 ;
@@ -2065,6 +2072,7 @@ void mingw_startup()
2065
2072
len = xwcstoutf (buffer , wenv [i ], maxlen );
2066
2073
environ [i ] = xmemdupz (buffer , len );
2067
2074
}
2075
+ environ [i ] = NULL ;
2068
2076
free (buffer );
2069
2077
2070
2078
/* initialize critical section for waitpid pinfo_t list */
0 commit comments