@@ -758,33 +758,40 @@ static int lookupenv(char **env, const char *name, size_t nmln)
758
758
759
759
/*
760
760
* If name contains '=', then sets the variable, otherwise it unsets it
761
+ * Size includes the terminating NULL. Env must have room for size + 1 entries
762
+ * (in case of insert). Returns the new size. Optionally frees removed entries.
761
763
*/
762
- static char * * do_putenv (char * * env , const char * name , int free_old )
764
+ static int do_putenv (char * * env , const char * name , int size , int free_old )
763
765
{
764
766
char * eq = strchrnul (name , '=' );
765
767
int i = lookupenv (env , name , eq - name );
766
768
767
769
if (i < 0 ) {
768
770
if (* eq ) {
769
- for (i = 0 ; env [i ]; i ++ )
770
- ;
771
- env = xrealloc (env , (i + 2 )* sizeof (* env ));
772
- env [i ] = (char * ) name ;
773
- env [i + 1 ] = NULL ;
771
+ env [size - 1 ] = (char * ) name ;
772
+ env [size ] = NULL ;
773
+ size ++ ;
774
774
}
775
775
}
776
776
else {
777
777
if (free_old )
778
778
free (env [i ]);
779
779
if (* eq )
780
780
env [i ] = (char * ) name ;
781
- else
781
+ else {
782
782
for (; env [i ]; i ++ )
783
783
env [i ] = env [i + 1 ];
784
+ size -- ;
785
+ }
784
786
}
785
- return env ;
787
+ return size ;
786
788
}
787
789
790
+ /* used number of elements of environ array, including terminating NULL */
791
+ static int environ_size = 0 ;
792
+ /* allocated size of environ array, in bytes */
793
+ static int environ_alloc = 0 ;
794
+
788
795
#undef getenv
789
796
char * mingw_getenv (const char * name )
790
797
{
@@ -804,7 +811,8 @@ char *mingw_getenv(const char *name)
804
811
805
812
int mingw_putenv (const char * namevalue )
806
813
{
807
- environ = do_putenv (environ , namevalue , 1 );
814
+ ALLOC_GROW (environ , (environ_size + 1 ) * sizeof (char * ), environ_alloc );
815
+ environ_size = do_putenv (environ , namevalue , environ_size , 1 );
808
816
return 0 ;
809
817
}
810
818
@@ -1003,31 +1011,28 @@ static char *path_lookup(const char *cmd, char **path, int exe_only)
1003
1011
static wchar_t * make_environment_block (char * * deltaenv )
1004
1012
{
1005
1013
wchar_t * wenvblk = NULL ;
1006
- int count = 0 ;
1007
- char * * e , * * tmpenv ;
1008
- int size = 0 , wenvsz = 0 , wenvpos = 0 ;
1014
+ char * * tmpenv ;
1015
+ int i = 0 , size = environ_size , wenvsz = 0 , wenvpos = 0 ;
1009
1016
1010
- while (environ [ count ])
1011
- count ++ ;
1017
+ while (deltaenv && deltaenv [ i ])
1018
+ i ++ ;
1012
1019
1013
- /* copy the environment */
1014
- tmpenv = xmalloc (sizeof ( * tmpenv ) * ( count + 1 ));
1015
- memcpy (tmpenv , environ , sizeof ( * tmpenv ) * ( count + 1 ));
1020
+ /* copy the environment, leaving space for changes */
1021
+ tmpenv = xmalloc (( size + i ) * sizeof ( char * ));
1022
+ memcpy (tmpenv , environ , size * sizeof ( char * ));
1016
1023
1017
1024
/* merge supplied environment changes into the temporary environment */
1018
- for (e = deltaenv ; e && * e ; e ++ )
1019
- tmpenv = do_putenv (tmpenv , * e , 0 );
1025
+ for (i = 0 ; deltaenv && deltaenv [ i ]; i ++ )
1026
+ size = do_putenv (tmpenv , deltaenv [ i ], size , 0 );
1020
1027
1021
1028
/* environment must be sorted */
1022
- for (count = 0 ; tmpenv [count ]; )
1023
- count ++ ;
1024
- qsort (tmpenv , count , sizeof (* tmpenv ), compareenv );
1029
+ qsort (tmpenv , size - 1 , sizeof (char * ), compareenv );
1025
1030
1026
1031
/* create environment block from temporary environment */
1027
- for (e = tmpenv ; * e ; e ++ ) {
1028
- size = 2 * strlen (* e ) + 2 ; /* +2 for final \0 */
1032
+ for (i = 0 ; tmpenv [ i ]; i ++ ) {
1033
+ size = 2 * strlen (tmpenv [ i ] ) + 2 ; /* +2 for final \0 */
1029
1034
ALLOC_GROW (wenvblk , (wenvpos + size ) * sizeof (wchar_t ), wenvsz );
1030
- wenvpos += xutftowcs (& wenvblk [wenvpos ], * e , size ) + 1 ;
1035
+ wenvpos += xutftowcs (& wenvblk [wenvpos ], tmpenv [ i ] , size ) + 1 ;
1031
1036
}
1032
1037
/* add final \0 terminator */
1033
1038
wenvblk [wenvpos ] = 0 ;
@@ -2060,7 +2065,9 @@ void mingw_startup()
2060
2065
maxlen = max (maxlen , wcslen (wenv [i ]));
2061
2066
2062
2067
/* nedmalloc can't free CRT memory, allocate resizable environment list */
2063
- environ = xcalloc (i + 1 , sizeof (char * ));
2068
+ environ = NULL ;
2069
+ environ_size = i + 1 ;
2070
+ ALLOC_GROW (environ , environ_size * sizeof (char * ), environ_alloc );
2064
2071
2065
2072
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
2066
2073
maxlen = 3 * maxlen + 1 ;
@@ -2077,6 +2084,7 @@ void mingw_startup()
2077
2084
len = xwcstoutf (buffer , wenv [i ], maxlen );
2078
2085
environ [i ] = xmemdupz (buffer , len );
2079
2086
}
2087
+ environ [i ] = NULL ;
2080
2088
free (buffer );
2081
2089
2082
2090
/* initialize critical section for waitpid pinfo_t list */
0 commit comments