summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/utf8_heavy.pl25
-rw-r--r--pod/perldiag.pod8
-rw-r--r--pod/perlunicode.pod4
-rw-r--r--t/op/taint.t16
4 files changed, 46 insertions, 7 deletions
diff --git a/lib/utf8_heavy.pl b/lib/utf8_heavy.pl
index 41cace887b..e0cdc7bb46 100644
--- a/lib/utf8_heavy.pl
+++ b/lib/utf8_heavy.pl
@@ -109,8 +109,18 @@ sub croak { require Carp; Carp::croak(@_) }
if (defined $caller1 && $type =~ /^I[ns]\w+$/) {
my $prop = "${caller1}::$type";
if (exists &{$prop}) {
+ # stolen from Scalar::Util::PP::tainted()
+ my $tainted;
+ {
+ local($@, $SIG{__DIE__}, $SIG{__WARN__});
+ local $^W = 0;
+ no warnings;
+ eval { kill 0 * $prop };
+ $tainted = 1 if $@ =~ /^Insecure/;
+ }
+ die "Insecure user-defined property \\p{$prop}\n"
+ if $tainted;
no strict 'refs';
-
$list = &{$prop}($caseless);
last GETFILE;
}
@@ -444,11 +454,12 @@ sub croak { require Carp; Carp::croak(@_) }
my $bits = $minbits;
if ($list) {
+ my $taint = substr($list,0,0); # maintain taint
my @tmp = split(/^/m, $list);
my %seen;
no warnings;
- $extras = join '', grep /^[^0-9a-fA-F]/, @tmp;
- $list = join '',
+ $extras = join '', $taint, grep /^[^0-9a-fA-F]/, @tmp;
+ $list = join '', $taint,
map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { /^([0-9a-fA-F]+)/; [ CORE::hex($1), $_ ] }
@@ -478,11 +489,13 @@ sub croak { require Carp; Carp::croak(@_) }
my @extras;
if ($extras) {
for my $x ($extras) {
+ my $taint = substr($x,0,0); # maintain taint
pos $x = 0;
while ($x =~ /^([^0-9a-fA-F\n])(.*)/mg) {
- my $char = $1;
- my $name = $2;
- print STDERR __LINE__, ": $1 => $2\n" if DEBUG;
+ my $char = "$1$taint";
+ my $name = "$2$taint";
+ print STDERR __LINE__, ": char [$char] => name [$name]\n"
+ if DEBUG;
if ($char =~ /[-+!&]/) {
my ($c,$t) = split(/::/, $name, 2); # bogus use of ::, really
my $subobj;
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 442106450f..aae2dd3b08 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -2188,6 +2188,14 @@ C<$ENV{ENV}>, C<$ENV{BASH_ENV}> or C<$ENV{TERM}> are derived from data
supplied (or potentially supplied) by the user. The script must set
the path to a known value, using trustworthy data. See L<perlsec>.
+=item Insecure user-defined property %s
+
+(F) Perl detected tainted data when trying to compile a regular
+expression that contains a call to a user-defined character property
+function, i.e. C<\p{IsFoo}> or C<\p{InFoo}>.
+See L<perlunicode/User-Defined Character Properties> and L<perlsec>.
+
+
=item Integer overflow in format string for %s
(F) The indexes and widths specified in the format string of C<printf()>
diff --git a/pod/perlunicode.pod b/pod/perlunicode.pod
index edb722d97f..97ac89e04d 100644
--- a/pod/perlunicode.pod
+++ b/pod/perlunicode.pod
@@ -801,6 +801,10 @@ the value of the flag, and one set of values will immutably be in effect
for all case-sensitive matches; the other set for all case-insensitive
matches.
+Note that if the regular expression is tainted, then perl will die rather
+than calling the subroutine, where the name of the subroutine is
+determined by the tainted data.
+
The subroutines must return a specially-formatted string, with one
or more newline-separated lines. Each line must be one of the following:
diff --git a/t/op/taint.t b/t/op/taint.t
index c2ab75d5a5..a040e464ff 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -17,7 +17,7 @@ use Config;
use File::Spec::Functions;
BEGIN { require './test.pl'; }
-plan tests => 687;
+plan tests => 689;
$| = 1;
@@ -2188,6 +2188,20 @@ end
is($s, 'xbc', "match bare regex taint value");
}
+{
+ # [perl #82616] security Issues with user-defined \p{} properties
+ # A using a tainted user-defined property should croak
+
+ sub IsA { sprintf "%02x", ord("A") }
+
+ my $prop = "IsA";
+ ok("A" =~ /\p{$prop}/, "user-defined property: non-tainted case");
+ $prop = "IsA$TAINT";
+ eval { "A" =~ /\p{$prop}/};
+ like($@, qr/Insecure user-defined property \\p{main::IsA}/,
+ "user-defined property: tainted case");
+}
+
# This may bomb out with the alarm signal so keep it last
SKIP: {
skip "No alarm()" unless $Config{d_alarm};