4.10.3-2: add gtktreeviewmodel fixes
[arch-packages.git] / perl / trunk / CVE-2016-2381_duplicate_env.diff
blob80adf62d2c2a690f19e686e79d3e4b972ee48aa8
1 From 83e7ebed7afa79a2f50eca6b6330eae7c3a02d36 Mon Sep 17 00:00:00 2001
2 From: Tony Cook <tony@develop-help.com>
3 Date: Wed, 27 Jan 2016 11:52:15 +1100
4 Subject: remove duplicate environment variables from environ
6 If we see duplicate environment variables while iterating over
7 environ[]:
9 a) make sure we use the same value in %ENV that getenv() returns.
11 Previously on a duplicate, %ENV would have the last entry for the name
12 from environ[], but a typical getenv() would return the first entry.
14 Rather than assuming all getenv() implementations return the first entry
15 explicitly call getenv() to ensure they agree.
17 b) remove duplicate entries from environ
19 Previously if there was a duplicate definition for a name in environ[]
20 setting that name in %ENV could result in an unsafe value being passed
21 to a child process, so ensure environ[] has no duplicates.
23 Patch-Name: fixes/CVE-2016-2381_duplicate_env.diff
24 ---
25 perl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
26 1 file changed, 49 insertions(+), 2 deletions(-)
28 diff --git a/perl.c b/perl.c
29 index 80a76c2..ed25429 100644
30 --- a/perl.c
31 +++ b/perl.c
32 @@ -4303,23 +4303,70 @@ S_init_postdump_symbols(pTHX_ int argc, char **argv, char **env)
34 if (env) {
35 char *s, *old_var;
36 + STRLEN nlen;
37 SV *sv;
38 + HV *dups = newHV();
40 for (; *env; env++) {
41 old_var = *env;
43 if (!(s = strchr(old_var,'=')) || s == old_var)
44 continue;
45 + nlen = s - old_var;
47 #if defined(MSDOS) && !defined(DJGPP)
48 *s = '\0';
49 (void)strupr(old_var);
50 *s = '=';
51 #endif
52 - sv = newSVpv(s+1, 0);
53 - (void)hv_store(hv, old_var, s - old_var, sv, 0);
54 + if (hv_exists(hv, old_var, nlen)) {
55 + const char *name = savepvn(old_var, nlen);
57 + /* make sure we use the same value as getenv(), otherwise code that
58 + uses getenv() (like setlocale()) might see a different value to %ENV
59 + */
60 + sv = newSVpv(PerlEnv_getenv(name), 0);
62 + /* keep a count of the dups of this name so we can de-dup environ later */
63 + if (hv_exists(dups, name, nlen))
64 + ++SvIVX(*hv_fetch(dups, name, nlen, 0));
65 + else
66 + (void)hv_store(dups, name, nlen, newSViv(1), 0);
68 + Safefree(name);
69 + }
70 + else {
71 + sv = newSVpv(s+1, 0);
72 + }
73 + (void)hv_store(hv, old_var, nlen, sv, 0);
74 if (env_is_not_environ)
75 mg_set(sv);
77 + if (HvKEYS(dups)) {
78 + /* environ has some duplicate definitions, remove them */
79 + HE *entry;
80 + hv_iterinit(dups);
81 + while ((entry = hv_iternext_flags(dups, 0))) {
82 + STRLEN nlen;
83 + const char *name = HePV(entry, nlen);
84 + IV count = SvIV(HeVAL(entry));
85 + IV i;
86 + SV **valp = hv_fetch(hv, name, nlen, 0);
88 + assert(valp);
90 + /* try to remove any duplicate names, depending on the
91 + * implementation used in my_setenv() the iteration might
92 + * not be necessary, but let's be safe.
93 + */
94 + for (i = 0; i < count; ++i)
95 + my_setenv(name, 0);
97 + /* and set it back to the value we set $ENV{name} to */
98 + my_setenv(name, SvPV_nolen(*valp));
99 + }
101 + SvREFCNT_dec_NN(dups);
103 #endif /* USE_ENVIRON_ARRAY */
104 #endif /* !PERL_MICRO */