Skip to content

Commit 0589f07

Browse files
iabynsteve-m-hay
authored andcommitted
Perl_my_setenv(); handle integer wrap
RT #133204 Wean this function off int/I32 and onto UV/Size_t. Also, replace all malloc-ish calls with a wrapper that does overflow checks, In particular, it was doing (nlen + vlen + 2) which could wrap when the combined length of the environment variable name and value exceeded around 0x7fffffff. The wrapper check function is probably overkill, but belt and braces... NB this function has several variant parts, #ifdef'ed by platform type; I have blindly changed the parts that aren't compiled under linux. (cherry picked from commit 34716e2)
1 parent 94027dc commit 0589f07

File tree

1 file changed

+53
-23
lines changed

1 file changed

+53
-23
lines changed

util.c

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
20662098
void
20672099
Perl_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

Comments
 (0)