@@ -966,6 +966,10 @@ static int do_putenv(char **env, const char *name, int size, int free_old);
966
966
static int environ_size = 0 ;
967
967
/* allocated size of environ array, in bytes */
968
968
static int environ_alloc = 0 ;
969
+ /* used as a indicator when the environment has been changed outside mingw.c */
970
+ static char * * saved_environ ;
971
+
972
+ static void maybe_reinitialize_environ (void );
969
973
970
974
/*
971
975
* Create environment block suitable for CreateProcess. Merges current
@@ -975,21 +979,24 @@ static wchar_t *make_environment_block(char **deltaenv)
975
979
{
976
980
wchar_t * wenvblk = NULL ;
977
981
char * * tmpenv ;
978
- int i = 0 , size = environ_size , wenvsz = 0 , wenvpos = 0 ;
982
+ int i = 0 , size , wenvsz = 0 , wenvpos = 0 ;
983
+
984
+ maybe_reinitialize_environ ();
985
+ size = environ_size ;
979
986
980
- while (deltaenv && deltaenv [i ])
987
+ while (deltaenv && deltaenv [i ] && * deltaenv [ i ] )
981
988
i ++ ;
982
989
983
990
/* copy the environment, leaving space for changes */
984
991
tmpenv = xmalloc ((size + i ) * sizeof (char * ));
985
992
memcpy (tmpenv , environ , size * sizeof (char * ));
986
993
987
994
/* merge supplied environment changes into the temporary environment */
988
- for (i = 0 ; deltaenv && deltaenv [i ]; i ++ )
995
+ for (i = 0 ; deltaenv && deltaenv [i ] && * deltaenv [ i ] ; i ++ )
989
996
size = do_putenv (tmpenv , deltaenv [i ], size , 0 );
990
997
991
998
/* create environment block from temporary environment */
992
- for (i = 0 ; tmpenv [i ]; i ++ ) {
999
+ for (i = 0 ; tmpenv [i ] && * tmpenv [ i ] ; i ++ ) {
993
1000
size = 2 * strlen (tmpenv [i ]) + 2 ; /* +2 for final \0 */
994
1001
ALLOC_GROW (wenvblk , (wenvpos + size ) * sizeof (wchar_t ), wenvsz );
995
1002
wenvpos += xutftowcs (& wenvblk [wenvpos ], tmpenv [i ], size ) + 1 ;
@@ -1278,6 +1285,41 @@ static int compareenv(const void *v1, const void *v2)
1278
1285
}
1279
1286
}
1280
1287
1288
+ /*
1289
+ * Functions implemented outside Git are able to modify the environment,
1290
+ * too. For example, cURL's curl_global_init() function sets the CHARSET
1291
+ * environment variable (at least in certain circumstances).
1292
+ *
1293
+ * Therefore we need to be *really* careful *not* to assume that we have
1294
+ * sole control over the environment and reinitalize it when necessary.
1295
+ */
1296
+ static void maybe_reinitialize_environ (void )
1297
+ {
1298
+ int i ;
1299
+
1300
+ if (!saved_environ ) {
1301
+ warning ("MinGW environment not initialized yet" );
1302
+ return ;
1303
+ }
1304
+
1305
+ if (environ_size <= 0 )
1306
+ return ;
1307
+
1308
+ if (saved_environ != environ )
1309
+ /* We have *no* idea how much space was allocated outside */
1310
+ environ_alloc = 0 ;
1311
+ else if (!environ [environ_size - 1 ])
1312
+ return ; /* still consistent */
1313
+
1314
+ for (i = 0 ; environ [i ] && * environ [i ]; i ++ )
1315
+ ; /* continue counting */
1316
+ environ [i ] = NULL ;
1317
+ environ_size = i + 1 ;
1318
+
1319
+ /* sort environment for O(log n) getenv / putenv */
1320
+ qsort (environ , i , sizeof (char * ), compareenv );
1321
+ }
1322
+
1281
1323
static int bsearchenv (char * * env , const char * name , size_t size )
1282
1324
{
1283
1325
unsigned low = 0 , high = size ;
@@ -1301,7 +1343,7 @@ static int bsearchenv(char **env, const char *name, size_t size)
1301
1343
*/
1302
1344
static int do_putenv (char * * env , const char * name , int size , int free_old )
1303
1345
{
1304
- int i = bsearchenv (env , name , size - 1 );
1346
+ int i = size <= 0 ? -1 : bsearchenv (env , name , size - 1 );
1305
1347
1306
1348
/* optionally free removed / replaced entry */
1307
1349
if (i >= 0 && free_old )
@@ -1326,7 +1368,14 @@ static int do_putenv(char **env, const char *name, int size, int free_old)
1326
1368
char * mingw_getenv (const char * name )
1327
1369
{
1328
1370
char * value ;
1329
- int pos = bsearchenv (environ , name , environ_size - 1 );
1371
+ int pos ;
1372
+
1373
+ if (environ_size <= 0 )
1374
+ return NULL ;
1375
+
1376
+ maybe_reinitialize_environ ();
1377
+ pos = bsearchenv (environ , name , environ_size - 1 );
1378
+
1330
1379
if (pos < 0 )
1331
1380
return NULL ;
1332
1381
value = strchr (environ [pos ], '=' );
@@ -1335,7 +1384,9 @@ char *mingw_getenv(const char *name)
1335
1384
1336
1385
int mingw_putenv (const char * namevalue )
1337
1386
{
1387
+ maybe_reinitialize_environ ();
1338
1388
ALLOC_GROW (environ , (environ_size + 1 ) * sizeof (char * ), environ_alloc );
1389
+ saved_environ = environ ;
1339
1390
environ_size = do_putenv (environ , namevalue , environ_size , 1 );
1340
1391
return 0 ;
1341
1392
}
@@ -2223,7 +2274,7 @@ void mingw_startup()
2223
2274
*/
2224
2275
environ_size = i + 1 ;
2225
2276
environ_alloc = alloc_nr (environ_size * sizeof (char * ));
2226
- environ = malloc_startup (environ_alloc );
2277
+ saved_environ = environ = malloc_startup (environ_alloc );
2227
2278
2228
2279
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
2229
2280
maxlen = 3 * maxlen + 1 ;
0 commit comments