@@ -2061,8 +2061,40 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
20612061 *(s+(nlen+1+vlen)) = '\0'
20622062
20632063#ifdef USE_ENVIRON_ARRAY
2064- /* VMS' my_setenv() is in vms.c */
2064+
2065+ /* small wrapper for use by Perl_my_setenv that mallocs, or reallocs if
2066+ * 'current' is non-null, with up to three sizes that are added together.
2067+ * It handles integer overflow.
2068+ */
2069+ static char *
2070+ S_env_alloc (void * current , Size_t l1 , Size_t l2 , Size_t l3 , Size_t size )
2071+ {
2072+ void * p ;
2073+ Size_t sl , l = l1 + l2 ;
2074+
2075+ if (l < l2 )
2076+ goto panic ;
2077+ l += l3 ;
2078+ if (l < l3 )
2079+ goto panic ;
2080+ sl = l * size ;
2081+ if (sl < l )
2082+ goto panic ;
2083+
2084+ p = current
2085+ ? safesysrealloc (current , sl )
2086+ : safesysmalloc (sl );
2087+ if (p )
2088+ return (char * )p ;
2089+
2090+ panic :
2091+ croak_memory_wrap ();
2092+ }
2093+
2094+
2095+ /* VMS' my_setenv() is in vms.c */
20652096#if !defined(WIN32 ) && !defined(NETWARE )
2097+
20662098void
20672099Perl_my_setenv (pTHX_ const char * nam , const char * val )
20682100{
@@ -2078,28 +2110,27 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
20782110#ifndef PERL_USE_SAFE_PUTENV
20792111 if (!PL_use_safe_putenv ) {
20802112 /* most putenv()s leak, so we manipulate environ directly */
2081- I32 i ;
2082- const I32 len = strlen (nam );
2083- int nlen , vlen ;
2113+ UV i ;
2114+ Size_t vlen , nlen = strlen (nam );
20842115
20852116 /* where does it go? */
20862117 for (i = 0 ; environ [i ]; i ++ ) {
2087- if (strnEQ (environ [i ],nam ,len ) && environ [i ][len ] == '=' )
2118+ if (strnEQ (environ [i ], nam , nlen ) && environ [i ][nlen ] == '=' )
20882119 break ;
20892120 }
20902121
20912122 if (environ == PL_origenviron ) { /* need we copy environment? */
2092- I32 j ;
2093- I32 max ;
2123+ UV j , max ;
20942124 char * * tmpenv ;
20952125
20962126 max = i ;
20972127 while (environ [max ])
20982128 max ++ ;
2099- tmpenv = (char * * )safesysmalloc ((max + 2 ) * sizeof (char * ));
2129+ /* XXX shouldn't that be max+1 rather than max+2 ??? - DAPM */
2130+ tmpenv = (char * * )S_env_alloc (NULL , max , 2 , 0 , sizeof (char * ));
21002131 for (j = 0 ; j < max ; j ++ ) { /* copy environment */
2101- const int len = strlen (environ [j ]);
2102- tmpenv [j ] = ( char * ) safesysmalloc (( len + 1 ) * sizeof ( char ) );
2132+ const Size_t len = strlen (environ [j ]);
2133+ tmpenv [j ] = S_env_alloc ( NULL , len , 1 , 0 , 1 );
21032134 Copy (environ [j ], tmpenv [j ], len + 1 , char );
21042135 }
21052136 tmpenv [max ] = NULL ;
@@ -2118,15 +2149,15 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
21182149#endif
21192150 }
21202151 if (!environ [i ]) { /* does not exist yet */
2121- environ = (char * * )safesysrealloc (environ , ( i + 2 ) * sizeof (char * ));
2152+ environ = (char * * )S_env_alloc (environ , i , 2 , 0 , sizeof (char * ));
21222153 environ [i + 1 ] = NULL ; /* make sure it's null terminated */
21232154 }
21242155 else
21252156 safesysfree (environ [i ]);
2126- nlen = strlen ( nam );
2157+
21272158 vlen = strlen (val );
21282159
2129- environ [i ] = ( char * ) safesysmalloc (( nlen + vlen + 2 ) * sizeof ( char ) );
2160+ environ [i ] = S_env_alloc ( NULL , nlen , vlen , 2 , 1 );
21302161 /* all that work just for this */
21312162 my_setenv_format (environ [i ], nam , nlen , val , vlen );
21322163 } else {
@@ -2150,22 +2181,21 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
21502181 if (environ ) /* old glibc can crash with null environ */
21512182 (void )unsetenv (nam );
21522183 } else {
2153- const int nlen = strlen (nam );
2154- const int vlen = strlen (val );
2155- char * const new_env =
2156- (char * )safesysmalloc ((nlen + vlen + 2 ) * sizeof (char ));
2184+ const Size_t nlen = strlen (nam );
2185+ const Size_t vlen = strlen (val );
2186+ char * const new_env = S_env_alloc (NULL , nlen , vlen , 2 , 1 );
21572187 my_setenv_format (new_env , nam , nlen , val , vlen );
21582188 (void )putenv (new_env );
21592189 }
21602190# else /* ! HAS_UNSETENV */
21612191 char * new_env ;
2162- const int nlen = strlen (nam );
2163- int vlen ;
2192+ const Size_t nlen = strlen (nam );
2193+ Size_t vlen ;
21642194 if (!val ) {
21652195 val = "" ;
21662196 }
21672197 vlen = strlen (val );
2168- new_env = ( char * ) safesysmalloc (( nlen + vlen + 2 ) * sizeof ( char ) );
2198+ new_env = S_env_alloc ( NULL , nlen , vlen , 2 , 1 );
21692199 /* all that work just for this */
21702200 my_setenv_format (new_env , nam , nlen , val , vlen );
21712201 (void )putenv (new_env );
@@ -2187,14 +2217,14 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
21872217{
21882218 dVAR ;
21892219 char * envstr ;
2190- const int nlen = strlen (nam );
2191- int vlen ;
2220+ const Size_t nlen = strlen (nam );
2221+ Size_t vlen ;
21922222
21932223 if (!val ) {
21942224 val = "" ;
21952225 }
21962226 vlen = strlen (val );
2197- Newx ( envstr , nlen + vlen + 2 , char );
2227+ envstr = S_env_alloc ( NULL , nlen , vlen , 2 , 1 );
21982228 my_setenv_format (envstr , nam , nlen , val , vlen );
21992229 (void )PerlEnv_putenv (envstr );
22002230 Safefree (envstr );
0 commit comments