PATCH: [perl #120675] Unexpected tainting via regex using locale
authorKarl Williamson <public@khwilliamson.com>
Wed, 4 Dec 2013 17:06:04 +0000 (10:06 -0700)
committerKarl Williamson <public@khwilliamson.com>
Thu, 5 Dec 2013 02:52:39 +0000 (19:52 -0700)
Tainting should only be turned on if something that could be tainted is
actually tried.  Hence in a [bracketed character class], if the
character being matched is something like

    "a" =~ /([a-z])/l;

tainting isn't turned on because the match doesn't actually depend on
the locale definition.  That is, it would match regardless of the
locale.  Similarly,

    "A" =~ /([a-z])/l;

shouldn't turn on tainting because it shouldn't match no matter what
locale is in effect.  However, until this commit, this worked only
because of a compilte time optimization.  The following (from the
ticket) isn't optimized and didn't work until this commit:

    "foo.bar_baz" =~ /^(.*)[._](.*?)$/';

The [._] was causing tainting even though there is nothing in the
pattern that is locale-dependent.

This commit just moves the tainting to code branches where the locale
actually does matter.  It was just turning it on for any bracketed
character class where the target character didn't match any of the
explicit characters in the class.

lib/locale.t
regexec.c

index b15d297..6407a61 100644 (file)
@@ -278,6 +278,11 @@ check_taint      $+;
 check_taint      $1;
 check_taint_not  $2;
 
+"a" =~ /([a-z])/;
+check_taint_not $1, '"a" =~ /([a-z])/';
+"foo.bar_baz" =~ /^(.*)[._](.*?)$/;  # Bug 120675
+check_taint_not $1, '"foo.bar_baz" =~ /^(.*)[._](.*?)$/';
+
 # After all this tainting $a should be cool.
 
 check_taint_not  $a;
index 13ab3e1..5e4db06 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -7448,14 +7448,14 @@ S_reginclass(pTHX_ regexp * const prog, const regnode * const n, const U8* const
            match = TRUE;
        }
        else if (flags & ANYOF_LOCALE) {
-           RXp_MATCH_TAINTED_on(prog);
-
-           if ((flags & ANYOF_LOC_FOLD)
-                && ANYOF_BITMAP_TEST(n, PL_fold_locale[c]))
-           {
-               match = TRUE;
-           }
+           if (flags & ANYOF_LOC_FOLD) {
+                RXp_MATCH_TAINTED_on(prog);
+                if (ANYOF_BITMAP_TEST(n, PL_fold_locale[c])) {
+                    match = TRUE;
+                }
+            }
            else if (ANYOF_POSIXL_TEST_ANY_SET(n)) {
+                RXp_MATCH_TAINTED_on(prog);
 
                 /* The data structure is arranged so bits 0, 2, 4, ... are set
                  * if the class includes the Posix character class given by