Fix an integer wrap when allocating memory for an environment variable
This commit is contained in:
parent
81b715af2e
commit
9710c0391a
|
@ -0,0 +1,180 @@
|
||||||
|
From 34716e2a6ee2af96078d62b065b7785c001194be Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Mitchell <davem@iabyn.com>
|
||||||
|
Date: Fri, 29 Jun 2018 13:37:03 +0100
|
||||||
|
Subject: [PATCH] Perl_my_setenv(); handle integer wrap
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||||
|
---
|
||||||
|
util.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 53 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index 7282dd9cfe..c5c7becc0f 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -2061,8 +2061,40 @@ Perl_new_warnings_bitfield(pTHX_ STRLEN *buffer, const char *const bits,
|
||||||
|
*(s+(nlen+1+vlen)) = '\0'
|
||||||
|
|
||||||
|
#ifdef USE_ENVIRON_ARRAY
|
||||||
|
- /* VMS' my_setenv() is in vms.c */
|
||||||
|
+
|
||||||
|
+/* small wrapper for use by Perl_my_setenv that mallocs, or reallocs if
|
||||||
|
+ * 'current' is non-null, with up to three sizes that are added together.
|
||||||
|
+ * It handles integer overflow.
|
||||||
|
+ */
|
||||||
|
+static char *
|
||||||
|
+S_env_alloc(void *current, Size_t l1, Size_t l2, Size_t l3, Size_t size)
|
||||||
|
+{
|
||||||
|
+ void *p;
|
||||||
|
+ Size_t sl, l = l1 + l2;
|
||||||
|
+
|
||||||
|
+ if (l < l2)
|
||||||
|
+ goto panic;
|
||||||
|
+ l += l3;
|
||||||
|
+ if (l < l3)
|
||||||
|
+ goto panic;
|
||||||
|
+ sl = l * size;
|
||||||
|
+ if (sl < l)
|
||||||
|
+ goto panic;
|
||||||
|
+
|
||||||
|
+ p = current
|
||||||
|
+ ? safesysrealloc(current, sl)
|
||||||
|
+ : safesysmalloc(sl);
|
||||||
|
+ if (p)
|
||||||
|
+ return (char*)p;
|
||||||
|
+
|
||||||
|
+ panic:
|
||||||
|
+ croak_memory_wrap();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* VMS' my_setenv() is in vms.c */
|
||||||
|
#if !defined(WIN32) && !defined(NETWARE)
|
||||||
|
+
|
||||||
|
void
|
||||||
|
Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
||||||
|
{
|
||||||
|
@@ -2078,28 +2110,27 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
||||||
|
#ifndef PERL_USE_SAFE_PUTENV
|
||||||
|
if (!PL_use_safe_putenv) {
|
||||||
|
/* most putenv()s leak, so we manipulate environ directly */
|
||||||
|
- I32 i;
|
||||||
|
- const I32 len = strlen(nam);
|
||||||
|
- int nlen, vlen;
|
||||||
|
+ UV i;
|
||||||
|
+ Size_t vlen, nlen = strlen(nam);
|
||||||
|
|
||||||
|
/* where does it go? */
|
||||||
|
for (i = 0; environ[i]; i++) {
|
||||||
|
- if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
|
||||||
|
+ if (strnEQ(environ[i], nam, nlen) && environ[i][nlen] == '=')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environ == PL_origenviron) { /* need we copy environment? */
|
||||||
|
- I32 j;
|
||||||
|
- I32 max;
|
||||||
|
+ UV j, max;
|
||||||
|
char **tmpenv;
|
||||||
|
|
||||||
|
max = i;
|
||||||
|
while (environ[max])
|
||||||
|
max++;
|
||||||
|
- tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
|
||||||
|
+ /* XXX shouldn't that be max+1 rather than max+2 ??? - DAPM */
|
||||||
|
+ tmpenv = (char**)S_env_alloc(NULL, max, 2, 0, sizeof(char*));
|
||||||
|
for (j=0; j<max; j++) { /* copy environment */
|
||||||
|
- const int len = strlen(environ[j]);
|
||||||
|
- tmpenv[j] = (char*)safesysmalloc((len+1)*sizeof(char));
|
||||||
|
+ const Size_t len = strlen(environ[j]);
|
||||||
|
+ tmpenv[j] = S_env_alloc(NULL, len, 1, 0, 1);
|
||||||
|
Copy(environ[j], tmpenv[j], len+1, char);
|
||||||
|
}
|
||||||
|
tmpenv[max] = NULL;
|
||||||
|
@@ -2118,15 +2149,15 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (!environ[i]) { /* does not exist yet */
|
||||||
|
- environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
|
||||||
|
+ environ = (char**)S_env_alloc(environ, i, 2, 0, sizeof(char*));
|
||||||
|
environ[i+1] = NULL; /* make sure it's null terminated */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
safesysfree(environ[i]);
|
||||||
|
- nlen = strlen(nam);
|
||||||
|
+
|
||||||
|
vlen = strlen(val);
|
||||||
|
|
||||||
|
- environ[i] = (char*)safesysmalloc((nlen+vlen+2) * sizeof(char));
|
||||||
|
+ environ[i] = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
||||||
|
/* all that work just for this */
|
||||||
|
my_setenv_format(environ[i], nam, nlen, val, vlen);
|
||||||
|
} else {
|
||||||
|
@@ -2150,22 +2181,21 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
||||||
|
if (environ) /* old glibc can crash with null environ */
|
||||||
|
(void)unsetenv(nam);
|
||||||
|
} else {
|
||||||
|
- const int nlen = strlen(nam);
|
||||||
|
- const int vlen = strlen(val);
|
||||||
|
- char * const new_env =
|
||||||
|
- (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
|
||||||
|
+ const Size_t nlen = strlen(nam);
|
||||||
|
+ const Size_t vlen = strlen(val);
|
||||||
|
+ char * const new_env = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
||||||
|
my_setenv_format(new_env, nam, nlen, val, vlen);
|
||||||
|
(void)putenv(new_env);
|
||||||
|
}
|
||||||
|
# else /* ! HAS_UNSETENV */
|
||||||
|
char *new_env;
|
||||||
|
- const int nlen = strlen(nam);
|
||||||
|
- int vlen;
|
||||||
|
+ const Size_t nlen = strlen(nam);
|
||||||
|
+ Size_t vlen;
|
||||||
|
if (!val) {
|
||||||
|
val = "";
|
||||||
|
}
|
||||||
|
vlen = strlen(val);
|
||||||
|
- new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
|
||||||
|
+ new_env = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
||||||
|
/* all that work just for this */
|
||||||
|
my_setenv_format(new_env, nam, nlen, val, vlen);
|
||||||
|
(void)putenv(new_env);
|
||||||
|
@@ -2187,14 +2217,14 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
|
||||||
|
{
|
||||||
|
dVAR;
|
||||||
|
char *envstr;
|
||||||
|
- const int nlen = strlen(nam);
|
||||||
|
- int vlen;
|
||||||
|
+ const Size_t nlen = strlen(nam);
|
||||||
|
+ Size_t vlen;
|
||||||
|
|
||||||
|
if (!val) {
|
||||||
|
val = "";
|
||||||
|
}
|
||||||
|
vlen = strlen(val);
|
||||||
|
- Newx(envstr, nlen+vlen+2, char);
|
||||||
|
+ envstr = S_env_alloc(NULL, nlen, vlen, 2, 1);
|
||||||
|
my_setenv_format(envstr, nam, nlen, val, vlen);
|
||||||
|
(void)PerlEnv_putenv(envstr);
|
||||||
|
Safefree(envstr);
|
||||||
|
--
|
||||||
|
2.14.4
|
||||||
|
|
|
@ -153,6 +153,10 @@ Patch14: perl-5.27.8-hints-linux-Add-lphtread-to-lddlflags.patch
|
||||||
# Adjust tests to gdbm-1.15, RT#133295
|
# Adjust tests to gdbm-1.15, RT#133295
|
||||||
Patch15: perl-5.29.0-Remove-ext-GDBM_File-t-fatal.t.patch
|
Patch15: perl-5.29.0-Remove-ext-GDBM_File-t-fatal.t.patch
|
||||||
|
|
||||||
|
# Fix an integer wrap when allocating memory for an environment variable,
|
||||||
|
# RT#133204, in upstream after 5.29.0
|
||||||
|
Patch16: perl-5.29.0-Perl_my_setenv-handle-integer-wrap.patch
|
||||||
|
|
||||||
# Link XS modules to libperl.so with EU::CBuilder on Linux, bug #960048
|
# Link XS modules to libperl.so with EU::CBuilder on Linux, bug #960048
|
||||||
Patch200: perl-5.16.3-Link-XS-modules-to-libperl.so-with-EU-CBuilder-on-Li.patch
|
Patch200: perl-5.16.3-Link-XS-modules-to-libperl.so-with-EU-CBuilder-on-Li.patch
|
||||||
|
|
||||||
|
@ -2722,6 +2726,7 @@ Perl extension for Version Objects
|
||||||
%patch13 -p1
|
%patch13 -p1
|
||||||
%patch14 -p1
|
%patch14 -p1
|
||||||
%patch15 -p1
|
%patch15 -p1
|
||||||
|
%patch16 -p1
|
||||||
%patch200 -p1
|
%patch200 -p1
|
||||||
%patch201 -p1
|
%patch201 -p1
|
||||||
|
|
||||||
|
@ -2744,6 +2749,7 @@ perl -x patchlevel.h \
|
||||||
'Fedora Patch13: Fix executing arybase::_tie_it() in Safe compartement (RT#131588)' \
|
'Fedora Patch13: Fix executing arybase::_tie_it() in Safe compartement (RT#131588)' \
|
||||||
'Fedora Patch14: Link XS modules to pthread library to fix linking with -z defs' \
|
'Fedora Patch14: Link XS modules to pthread library to fix linking with -z defs' \
|
||||||
'Fedora Patch15: Adjust tests to gdbm-1.15 (RT#133295)' \
|
'Fedora Patch15: Adjust tests to gdbm-1.15 (RT#133295)' \
|
||||||
|
'Fedora Patch16: Fix an integer wrap when allocating memory for an environment variable (RT#133204)' \
|
||||||
'Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux' \
|
'Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux' \
|
||||||
'Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux' \
|
'Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux' \
|
||||||
%{nil}
|
%{nil}
|
||||||
|
@ -5034,6 +5040,8 @@ popd
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Jul 09 2018 Petr Pisar <ppisar@redhat.com> - 4:5.28.0-417
|
* Mon Jul 09 2018 Petr Pisar <ppisar@redhat.com> - 4:5.28.0-417
|
||||||
- Adjust tests to gdbm-1.15 (RT#133295)
|
- Adjust tests to gdbm-1.15 (RT#133295)
|
||||||
|
- Fix an integer wrap when allocating memory for an environment variable
|
||||||
|
(RT#133204)
|
||||||
|
|
||||||
* Wed Jun 27 2018 Jitka Plesnikova <jplesnik@redhat.com> - 4:5.28.0-416
|
* Wed Jun 27 2018 Jitka Plesnikova <jplesnik@redhat.com> - 4:5.28.0-416
|
||||||
- Stop providing old perl(MODULE_COMPAT_5.26.*)
|
- Stop providing old perl(MODULE_COMPAT_5.26.*)
|
||||||
|
|
Loading…
Reference in New Issue