In perl.git, the branch maint-5.24 has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/1addf2f85380133ce4aa5f2f1d35bac377e0d90a?hp=f8379d9f8dd3aac0eabe12edb11ed26281903ce7>

- Log -----------------------------------------------------------------
commit 1addf2f85380133ce4aa5f2f1d35bac377e0d90a
Author: Father Chrysostomos <[email protected]>
Date:   Thu Feb 23 08:34:07 2017 +0000

    Fix checks for tainted dir in $ENV{PATH}
    
    $ cat > foo
    print "What?!\n"
    ^D
    $ chmod +x foo
    $ ./perl -Ilib -Te '$ENV{PATH}="."; exec "foo"'
    Insecure directory in $ENV{PATH} while running with -T switch at -e line 1.
    
    That is what I expect to see.  But:
    
    $ ./perl -Ilib -Te '$ENV{PATH}="/\\:."; exec "foo"'
    What?!
    
    Perl is allowing the \ to escape the :, but the \ is not treated as an
    escape by the system, allowing a relative path in PATH to be consid-
    ered safe.
    
    (cherry picked from commit ba0a4150f6f1604df236035adf6df18bd43de88e)

M       embed.fnc
M       embed.h
M       mg.c
M       proto.h
M       t/op/taint.t
M       util.c

commit 93e39480947573cb85e287907a745faf061002f6
Author: Karl Williamson <[email protected]>
Date:   Sat Aug 27 19:16:17 2016 -0600

    PATCH: [perl #129038] Crash with s///l
    
    The cause of this was bad logic.  It thought it was dealing with UTF-8
    when it wasn't.
    
    (cherry picked from commit 109ac342a6bc5a3a67c3b52341607100cedafdf7)

M       regexec.c
M       t/re/subst.t
-----------------------------------------------------------------------

Summary of changes:
 embed.fnc    |  4 ++++
 embed.h      |  1 +
 mg.c         |  2 +-
 proto.h      |  3 +++
 regexec.c    | 27 +++++++++++++++------------
 t/op/taint.t | 18 +++++++++++++++++-
 t/re/subst.t | 19 ++++++++++++++++++-
 util.c       | 25 ++++++++++++++++++++++---
 8 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index a64ffbac74..d59eb35bc9 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -344,6 +344,10 @@ Ap |I32    |debstackptrs
 pR     |SV *   |defelem_target |NN SV *sv|NULLOK MAGIC *mg
 Anp    |char*  |delimcpy       |NN char* to|NN const char* toend|NN const 
char* from \
                                |NN const char* fromend|int delim|NN I32* retlen
+np     |char*  |delimcpy_no_escape|NN char* to|NN const char* toend \
+                                  |NN const char* from \
+                                  |NN const char* fromend|int delim \
+                                  |NN I32* retlen
 : Used in op.c, perl.c
 pM     |void   |delete_eval_scope
 Aprd    |OP*    |die_sv         |NN SV *baseex
diff --git a/embed.h b/embed.h
index 42c65b2eb0..5b2998d79e 100644
--- a/embed.h
+++ b/embed.h
@@ -1206,6 +1206,7 @@
 #define deb_stack_all()                Perl_deb_stack_all(aTHX)
 #define defelem_target(a,b)    Perl_defelem_target(aTHX_ a,b)
 #define delete_eval_scope()    Perl_delete_eval_scope(aTHX)
+#define delimcpy_no_escape     Perl_delimcpy_no_escape
 #define die_unwind(a)          Perl_die_unwind(aTHX_ a)
 #define do_aexec5(a,b,c,d,e)   Perl_do_aexec5(aTHX_ a,b,c,d,e)
 #define do_dump_pad(a,b,c,d)   Perl_do_dump_pad(aTHX_ a,b,c,d)
diff --git a/mg.c b/mg.c
index 4321a401ad..1c43c9dedb 100644
--- a/mg.c
+++ b/mg.c
@@ -1259,7 +1259,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
 #else
                const char path_sep = ':';
 #endif
-               s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
+               s = delimcpy_no_escape(tmpbuf, tmpbuf + sizeof tmpbuf,
                             s, strend, path_sep, &i);
                s++;
                if (i >= (I32)sizeof tmpbuf   /* too long -- assume the worst */
diff --git a/proto.h b/proto.h
index fb4ee29508..8d4713b096 100644
--- a/proto.h
+++ b/proto.h
@@ -659,6 +659,9 @@ PERL_CALLCONV void  Perl_delete_eval_scope(pTHX);
 PERL_CALLCONV char*    Perl_delimcpy(char* to, const char* toend, const char* 
from, const char* fromend, int delim, I32* retlen);
 #define PERL_ARGS_ASSERT_DELIMCPY      \
        assert(to); assert(toend); assert(from); assert(fromend); assert(retlen)
+PERL_CALLCONV char*    Perl_delimcpy_no_escape(char* to, const char* toend, 
const char* from, const char* fromend, int delim, I32* retlen);
+#define PERL_ARGS_ASSERT_DELIMCPY_NO_ESCAPE    \
+       assert(to); assert(toend); assert(from); assert(fromend); assert(retlen)
 PERL_CALLCONV void     Perl_despatch_signals(pTHX);
 PERL_CALLCONV_NO_RET OP*       Perl_die(pTHX_ const char* pat, ...)
                        __attribute__noreturn__
diff --git a/regexec.c b/regexec.c
index cdaa95cce5..5735b997fd 100644
--- a/regexec.c
+++ b/regexec.c
@@ -6191,23 +6191,26 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char 
*startpos, regnode *prog)
                 if (! (to_complement ^ cBOOL(isFOO_lc(FLAGS(scan), (U8) 
nextchr)))) {
                     sayNO;
                 }
+
+                locinput++;
+                break;
             }
-            else if (UTF8_IS_DOWNGRADEABLE_START(nextchr)) {
-                if (! (to_complement ^ cBOOL(isFOO_lc(FLAGS(scan),
-                                               
EIGHT_BIT_UTF8_TO_NATIVE(nextchr,
-                                               *(locinput + 1))))))
-                {
-                    sayNO;
-                }
-            }
-            else { /* Here, must be an above Latin-1 code point */
+
+            if (! UTF8_IS_DOWNGRADEABLE_START(nextchr)) { /* An above Latin-1 
code point */
                 _CHECK_AND_OUTPUT_WIDE_LOCALE_UTF8_MSG(locinput, 
reginfo->strend);
                 goto utf8_posix_above_latin1;
             }
 
-            /* Here, must be utf8 */
-            locinput += UTF8SKIP(locinput);
-            break;
+            /* Here is a UTF-8 variant code point below 256 and the target is
+             * UTF-8 */
+            if (! (to_complement ^ cBOOL(isFOO_lc(FLAGS(scan),
+                                            EIGHT_BIT_UTF8_TO_NATIVE(nextchr,
+                                            *(locinput + 1))))))
+            {
+                sayNO;
+            }
+
+            goto increment_locinput;
 
         case NPOSIXD:   /* \W or [:^punct:] etc. under /d */
             to_complement = 1;
diff --git a/t/op/taint.t b/t/op/taint.t
index 101c6da427..846ac23f0d 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -17,7 +17,7 @@ BEGIN {
 use strict;
 use Config;
 
-plan tests => 808;
+plan tests => 812;
 
 $| = 1;
 
@@ -187,6 +187,22 @@ my $TEST = 'TEST';
        like($@, qr/^Insecure (?:directory in )?\$ENV\{PATH}/);
     }
 
+    # Relative paths in $ENV{PATH} are always implicitly tainted.
+    SKIP: {
+        skip "Do these work on VMS?", 4 if $Is_VMS;
+        skip "Not applicable to DOSish systems", 4 if! $tmp;
+
+        local $ENV{PATH} = '.';
+        is(eval { `$echo 1` }, undef);
+        like($@, qr/^Insecure (?:directory in )?\$ENV\{PATH}/);
+
+        # Backslash should not fool perl into thinking that this is one
+        # path.
+        local $ENV{PATH} = '/\:.';
+        is(eval { `$echo 1` }, undef);
+        like($@, qr/^Insecure (?:directory in )?\$ENV\{PATH}/);
+    }
+
     SKIP: {
         skip "This is not VMS", 4 unless $Is_VMS;
 
diff --git a/t/re/subst.t b/t/re/subst.t
index 26a78c774d..49d28e9689 100644
--- a/t/re/subst.t
+++ b/t/re/subst.t
@@ -11,7 +11,7 @@ BEGIN {
     require './loc_tools.pl';
 }
 
-plan( tests => 270 );
+plan( tests => 271 );
 
 $_ = 'david';
 $a = s/david/rules/r;
@@ -1102,3 +1102,20 @@ SKIP: {
     $s =~ s/..\G//g;
     is($s, "\x{123}", "#RT 126260 gofs");
 }
+
+SKIP: {
+    if (! locales_enabled('LC_CTYPE')) {
+        skip "Can't test locale", 1;
+    }
+
+    #  To cause breakeage, we need a locale in which \xff matches whatever
+    #  POSIX class is used in the pattern.  Easiest is C, with \W.
+    fresh_perl_is('    use POSIX qw(locale_h);
+                       setlocale(&POSIX::LC_CTYPE, "C");
+                       my $s = "\xff";
+                       $s =~ s/\W//l;
+                       print qq(ok$s\n)',
+                   "ok\n",
+                   {stderr => 1 },
+                   '[perl #129038 ] s/\xff//l no longer crashes');
+}
diff --git a/util.c b/util.c
index 89c44e735d..b64e87dd32 100644
--- a/util.c
+++ b/util.c
@@ -524,15 +524,17 @@ Free_t   Perl_mfree (Malloc_t where)
 
 /* copy a string up to some (non-backslashed) delimiter, if any */
 
-char *
-Perl_delimcpy(char *to, const char *toend, const char *from, const char 
*fromend, int delim, I32 *retlen)
+static char *
+S_delimcpy(char *to, const char *toend, const char *from,
+          const char *fromend, int delim, I32 *retlen,
+          const bool allow_escape)
 {
     I32 tolen;
 
     PERL_ARGS_ASSERT_DELIMCPY;
 
     for (tolen = 0; from < fromend; from++, tolen++) {
-       if (*from == '\\') {
+       if (allow_escape && *from == '\\') {
            if (from[1] != delim) {
                if (to < toend)
                    *to++ = *from;
@@ -551,6 +553,23 @@ Perl_delimcpy(char *to, const char *toend, const char 
*from, const char *fromend
     return (char *)from;
 }
 
+char *
+Perl_delimcpy(char *to, const char *toend, const char *from, const char 
*fromend, int delim, I32 *retlen)
+{
+    PERL_ARGS_ASSERT_DELIMCPY;
+
+    return S_delimcpy(to, toend, from, fromend, delim, retlen, 1);
+}
+
+char *
+Perl_delimcpy_no_escape(char *to, const char *toend, const char *from,
+                       const char *fromend, int delim, I32 *retlen)
+{
+    PERL_ARGS_ASSERT_DELIMCPY_NO_ESCAPE;
+
+    return S_delimcpy(to, toend, from, fromend, delim, retlen, 0);
+}
+
 /* return ptr to little string in big string, NULL if not found */
 /* This routine was donated by Corey Satten. */
 

--
Perl5 Master Repository

Reply via email to