|
|
b1bb9c |
From 17858779e42103ae815c8cf7c4d390207e485856 Mon Sep 17 00:00:00 2001
|
|
|
b1bb9c |
From: Jitka Plesnikova <jplesnik@redhat.com>
|
|
|
b1bb9c |
Date: Mon, 7 Jan 2019 13:38:36 +0100
|
|
|
b1bb9c |
Subject: [PATCH] Perl_my_setenv(); handle integer wrap
|
|
|
b1bb9c |
|
|
|
b1bb9c |
RT #133204
|
|
|
b1bb9c |
|
|
|
b1bb9c |
Wean this function off int/I32 and onto UV/Size_t.
|
|
|
b1bb9c |
Also, replace all malloc-ish calls with a wrapper that does
|
|
|
b1bb9c |
overflow checks,
|
|
|
b1bb9c |
|
|
|
b1bb9c |
In particular, it was doing (nlen + vlen + 2) which could wrap when
|
|
|
b1bb9c |
the combined length of the environment variable name and value
|
|
|
b1bb9c |
exceeded around 0x7fffffff.
|
|
|
b1bb9c |
|
|
|
b1bb9c |
The wrapper check function is probably overkill, but belt and braces...
|
|
|
b1bb9c |
|
|
|
b1bb9c |
NB this function has several variant parts, #ifdef'ed by platform
|
|
|
b1bb9c |
type; I have blindly changed the parts that aren't compiled under linux.
|
|
|
b1bb9c |
|
|
|
b1bb9c |
Backported David Mitchell's patch to 5.16.3
|
|
|
b1bb9c |
---
|
|
|
b1bb9c |
util.c | 75 ++++++++++++++++++++++++++++++++++++++++------------------
|
|
|
b1bb9c |
1 file changed, 52 insertions(+), 23 deletions(-)
|
|
|
b1bb9c |
|
|
|
b1bb9c |
diff --git a/util.c b/util.c
|
|
|
b1bb9c |
index c1dca62..1357ad5 100644
|
|
|
b1bb9c |
--- a/util.c
|
|
|
b1bb9c |
+++ b/util.c
|
|
|
b1bb9c |
@@ -2029,7 +2029,38 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
|
|
|
b1bb9c |
*(s+(nlen+1+vlen)) = '\0'
|
|
|
b1bb9c |
|
|
|
b1bb9c |
#ifdef USE_ENVIRON_ARRAY
|
|
|
b1bb9c |
- /* VMS' my_setenv() is in vms.c */
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+/* small wrapper for use by Perl_my_setenv that mallocs, or reallocs if
|
|
|
b1bb9c |
+ * 'current' is non-null, with up to three sizes that are added together.
|
|
|
b1bb9c |
+ * It handles integer overflow.
|
|
|
b1bb9c |
+ */
|
|
|
b1bb9c |
+static char *
|
|
|
b1bb9c |
+S_env_alloc(void *current, Size_t l1, Size_t l2, Size_t l3, Size_t size)
|
|
|
b1bb9c |
+{
|
|
|
b1bb9c |
+ void *p;
|
|
|
b1bb9c |
+ Size_t sl, l = l1 + l2;
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+ if (l < l2)
|
|
|
b1bb9c |
+ goto panic;
|
|
|
b1bb9c |
+ l += l3;
|
|
|
b1bb9c |
+ if (l < l3)
|
|
|
b1bb9c |
+ goto panic;
|
|
|
b1bb9c |
+ sl = l * size;
|
|
|
b1bb9c |
+ if (sl < l)
|
|
|
b1bb9c |
+ goto panic;
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+ p = current
|
|
|
b1bb9c |
+ ? safesysrealloc(current, sl)
|
|
|
b1bb9c |
+ : safesysmalloc(sl);
|
|
|
b1bb9c |
+ if (p)
|
|
|
b1bb9c |
+ return (char*)p;
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+ panic:
|
|
|
b1bb9c |
+ Perl_croak_nocontext("%s", PL_memory_wrap);
|
|
|
b1bb9c |
+}
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
+/* VMS' my_setenv() is in vms.c */
|
|
|
b1bb9c |
#if !defined(WIN32) && !defined(NETWARE)
|
|
|
b1bb9c |
void
|
|
|
b1bb9c |
Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
|
|
b1bb9c |
@@ -2043,28 +2074,27 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
|
|
b1bb9c |
#ifndef PERL_USE_SAFE_PUTENV
|
|
|
b1bb9c |
if (!PL_use_safe_putenv) {
|
|
|
b1bb9c |
/* most putenv()s leak, so we manipulate environ directly */
|
|
|
b1bb9c |
- register I32 i;
|
|
|
b1bb9c |
- register const I32 len = strlen(nam);
|
|
|
b1bb9c |
- int nlen, vlen;
|
|
|
b1bb9c |
+ UV i;
|
|
|
b1bb9c |
+ Size_t vlen, nlen = strlen(nam);
|
|
|
b1bb9c |
|
|
|
b1bb9c |
/* where does it go? */
|
|
|
b1bb9c |
for (i = 0; environ[i]; i++) {
|
|
|
b1bb9c |
- if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
|
|
|
b1bb9c |
+ if (strnEQ(environ[i], nam, nlen) && environ[i][nlen] == '=')
|
|
|
b1bb9c |
break;
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
|
|
|
b1bb9c |
if (environ == PL_origenviron) { /* need we copy environment? */
|
|
|
b1bb9c |
- I32 j;
|
|
|
b1bb9c |
- I32 max;
|
|
|
b1bb9c |
+ UV j, max;
|
|
|
b1bb9c |
char **tmpenv;
|
|
|
b1bb9c |
|
|
|
b1bb9c |
max = i;
|
|
|
b1bb9c |
while (environ[max])
|
|
|
b1bb9c |
max++;
|
|
|
b1bb9c |
- tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
|
|
|
b1bb9c |
+ /* XXX shouldn't that be max+1 rather than max+2 ??? - DAPM */
|
|
|
b1bb9c |
+ tmpenv = (char**)S_env_alloc(NULL, max, 2, 0, sizeof(char*));
|
|
|
b1bb9c |
for (j=0; j
|
|
|
b1bb9c |
- const int len = strlen(environ[j]);
|
|
|
b1bb9c |
- tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
|
|
|
b1bb9c |
+ const Size_t len = strlen(environ[j]);
|
|
|
b1bb9c |
+ tmpenv[j] = S_env_alloc(NULL, len, 1, 0, 1);
|
|
|
b1bb9c |
Copy(environ[j], tmpenv[j], len+1, char);
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
tmpenv[max] = NULL;
|
|
|
b1bb9c |
@@ -2079,15 +2109,15 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
|
|
b1bb9c |
return;
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
if (!environ[i]) { /* does not exist yet */
|
|
|
b1bb9c |
- environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
|
|
|
b1bb9c |
+ environ = (char**)S_env_alloc(environ, i, 2, 0, sizeof(char*));
|
|
|
b1bb9c |
environ[i+1] = NULL; /* make sure it's null terminated */
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
else
|
|
|
b1bb9c |
safesysfree(environ[i]);
|
|
|
b1bb9c |
- nlen = strlen(nam);
|
|
|
b1bb9c |
+
|
|
|
b1bb9c |
vlen = strlen(val);
|
|
|
b1bb9c |
|
|
|
b1bb9c |
- environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
|
|
|
b1bb9c |
+ environ[i] = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
|
|
b1bb9c |
/* all that work just for this */
|
|
|
b1bb9c |
my_setenv_format(environ[i], nam, nlen, val, vlen);
|
|
|
b1bb9c |
} else {
|
|
|
b1bb9c |
@@ -2107,22 +2137,21 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
|
|
b1bb9c |
if (val == NULL) {
|
|
|
b1bb9c |
(void)unsetenv(nam);
|
|
|
b1bb9c |
} else {
|
|
|
b1bb9c |
- const int nlen = strlen(nam);
|
|
|
b1bb9c |
- const int vlen = strlen(val);
|
|
|
b1bb9c |
- char * const new_env =
|
|
|
b1bb9c |
- (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
|
|
|
b1bb9c |
+ const Size_t nlen = strlen(nam);
|
|
|
b1bb9c |
+ const Size_t vlen = strlen(val);
|
|
|
b1bb9c |
+ char * const new_env = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
|
|
b1bb9c |
my_setenv_format(new_env, nam, nlen, val, vlen);
|
|
|
b1bb9c |
(void)putenv(new_env);
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
# else /* ! HAS_UNSETENV */
|
|
|
b1bb9c |
char *new_env;
|
|
|
b1bb9c |
- const int nlen = strlen(nam);
|
|
|
b1bb9c |
- int vlen;
|
|
|
b1bb9c |
+ const Size_t nlen = strlen(nam);
|
|
|
b1bb9c |
+ Size_t vlen;
|
|
|
b1bb9c |
if (!val) {
|
|
|
b1bb9c |
val = "";
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
vlen = strlen(val);
|
|
|
b1bb9c |
- new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
|
|
|
b1bb9c |
+ new_env = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
|
|
b1bb9c |
/* all that work just for this */
|
|
|
b1bb9c |
my_setenv_format(new_env, nam, nlen, val, vlen);
|
|
|
b1bb9c |
(void)putenv(new_env);
|
|
|
b1bb9c |
@@ -2141,14 +2170,14 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
|
|
b1bb9c |
{
|
|
|
b1bb9c |
dVAR;
|
|
|
b1bb9c |
register char *envstr;
|
|
|
b1bb9c |
- const int nlen = strlen(nam);
|
|
|
b1bb9c |
- int vlen;
|
|
|
b1bb9c |
+ const Size_t nlen = strlen(nam);
|
|
|
b1bb9c |
+ Size_t vlen;
|
|
|
b1bb9c |
|
|
|
b1bb9c |
if (!val) {
|
|
|
b1bb9c |
val = "";
|
|
|
b1bb9c |
}
|
|
|
b1bb9c |
vlen = strlen(val);
|
|
|
b1bb9c |
- Newx(envstr, nlen+vlen+2, char);
|
|
|
b1bb9c |
+ envstr = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
|
|
b1bb9c |
my_setenv_format(envstr, nam, nlen, val, vlen);
|
|
|
b1bb9c |
(void)PerlEnv_putenv(envstr);
|
|
|
b1bb9c |
Safefree(envstr);
|
|
|
b1bb9c |
--
|
|
|
b1bb9c |
2.17.2
|
|
|
b1bb9c |
|