Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PATCH] Add blacklist and whitelist functionality to Locale::Maketext #15282

Closed
p5pRT opened this issue Apr 18, 2016 · 13 comments
Closed

[PATCH] Add blacklist and whitelist functionality to Locale::Maketext #15282

p5pRT opened this issue Apr 18, 2016 · 13 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 18, 2016

Migrated from rt.perl.org#127923 (status was 'resolved')

Searchable as RT127923$

@p5pRT
Copy link
Author

p5pRT commented Apr 18, 2016

From @lightsey

Created by @lightsey

The patch attached to this bug report adds support for blacklist
and whitelist functionality directly to Locale​::Maketext.

Webapps that use Locale​::Maketext tend to pre-filter maketext
strings to limit the types of bracket notation that are allowed.
By rolling this directly into Locale​::Maketext, they can limit
the availailable bracket notation methods in a simpler and more
efficient fashion.

Perl Info

Flags:
    category=library
    severity=wishlist
    module=Locale::Maketext

Site configuration information for perl 5.22.1:

Configured by Debian Project at Sun Mar 13 11:54:18 UTC 2016.

Summary of my perl5 (revision 5 version 22 subversion 1) configuration:
   
  Platform:
    osname=linux, osvers=3.16.0, archname=x86_64-linux-gnu-thread-multi
    uname='linux localhost 3.16.0 #1 smp debian 3.16.0 x86_64 gnulinux
'
    config_args='-Dusethreads -Duselargefiles -Dcc=x86_64-linux-gnu-gcc 
-Dcpp=x86_64-linux-gnu-cpp -Dld=x86_64-linux-gnu-gcc -Dccflags=-DDEBIAN 
-Wdate-time -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong
-Wformat -Werror=format-security -Dldflags= -Wl,-z,relro -Dlddlflags=-
shared -Wl,-z,relro -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu
-Dprefix=/usr -Dprivlib=/usr/share/perl/5.22 -Darchlib=/usr/lib/x86_64-
linux-gnu/perl/5.22 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/x86_64-linux-gnu/perl5/5.22
-Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.22.1
-Dsitearch=/usr/local/lib/x86_64-linux-gnu/perl/5.22.1
-Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3
-Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3
-Duse64bitint -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-
pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -Ui_libutil
-Uversiononly -DDEBUGGING=-g -Doptimize=-O2 -dEs -Duseshrplib
-Dlibperl=libperl.so.5.22.1'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-linux-gnu-gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE
-DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -g',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-
aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='5.3.1 20160307', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678,
doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define,
longdblsize=16, longdblkind=3
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-linux-gnu-gcc', ldflags =' -fstack-protector-strong
-L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed 
/usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu
/lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=libc-2.22.so, so=so, useshrplib=true, libperl=libperl.so.5.22
    gnulibc_version='2.22'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib -fstack-
protector-strong'

Locally applied patches:
    DEBPKG:debian/cpan_definstalldirs - Provide a sensible INSTALLDIRS
default for modules installed from CPAN.
    DEBPKG:debian/db_file_ver - http://bugs.debian.org/340047 Remove
overly restrictive DB_File version check.
    DEBPKG:debian/doc_info - Replace generic man(1) instructions with
Debian-specific information.
    DEBPKG:debian/enc2xs_inc - http://bugs.debian.org/290336 Tweak
enc2xs to follow symlinks and ignore missing @INC directories.
    DEBPKG:debian/errno_ver - http://bugs.debian.org/343351 Remove
Errno version check due to upgrade problems with long-running
processes.
    DEBPKG:debian/libperl_embed_doc - http://bugs.debian.org/186778
Note that libperl-dev package is required for embedded linking
    DEBPKG:fixes/respect_umask - Respect umask during installation
    DEBPKG:debian/writable_site_dirs - Set umask approproately for site
install directories
    DEBPKG:debian/extutils_set_libperl_path - EU:MM: set location of
libperl.a under /usr/lib
    DEBPKG:debian/no_packlist_perllocal - Don't install .packlist or
perllocal.pod for perl or vendor
    DEBPKG:debian/fakeroot - Postpone LD_LIBRARY_PATH evaluation to the
binary targets.
    DEBPKG:debian/instmodsh_doc - Debian policy doesn't install
.packlist files for core or vendor.
    DEBPKG:debian/ld_run_path - Remove standard libs from LD_RUN_PATH
as per Debian policy.
    DEBPKG:debian/libnet_config_path - Set location of libnet.cfg to
/etc/perl/Net as /usr may not be writable.
    DEBPKG:debian/mod_paths - Tweak @INC ordering for Debian
    DEBPKG:debian/prune_libs - http://bugs.debian.org/128355 Prune the
list of libraries wanted to what we actually need.
    DEBPKG:fixes/net_smtp_docs - [rt.cpan.org #36038] http://bugs.debia
n.org/100195 Document the Net::SMTP 'Port' option
    DEBPKG:debian/perlivp - http://bugs.debian.org/510895 Make perlivp
skip include directories in /usr/local
    DEBPKG:debian/deprecate-with-apt - http://bugs.debian.org/747628
Point users to Debian packages of deprecated core modules
    DEBPKG:debian/squelch-locale-warnings - http://bugs.debian.org/5087
64 Squelch locale warnings in Debian package maintainer scripts
    DEBPKG:debian/skip-upstream-git-tests - Skip tests specific to the
upstream Git repository
    DEBPKG:debian/patchlevel - http://bugs.debian.org/567489 List
packaged patches for 5.22.1-9 in patchlevel.h
    DEBPKG:debian/skip-kfreebsd-crash - http://bugs.debian.org/628493
[perl #96272] Skip a crashing test case in t/op/threads.t on
GNU/kFreeBSD
    DEBPKG:fixes/document_makemaker_ccflags - http://bugs.debian.org/62
8522 [rt.cpan.org #68613] Document that CCFLAGS should include
$Config{ccflags}
    DEBPKG:debian/find_html2text - http://bugs.debian.org/640479
Configure CPAN::Distribution with correct name of html2text
    DEBPKG:debian/perl5db-x-terminal-emulator.patch - http://bugs.debia
n.org/668490 Invoke x-terminal-emulator rather than xterm in perl5db.pl
    DEBPKG:debian/cpan-missing-site-dirs - http://bugs.debian.org/68884
2 Fix CPAN::FirstTime defaults with nonexisting site dirs if a parent
is writable
    DEBPKG:fixes/memoize_storable_nstore - [rt.cpan.org #77790] http://
bugs.debian.org/587650 Memoize::Storable: respect 'nstore' option not
respected
    DEBPKG:debian/regen-skip - Skip a regeneration check in unrelated
git repositories
    DEBPKG:debian/makemaker-pasthru - http://bugs.debian.org/758471
Pass LD settings through to subdirectories
    DEBPKG:fixes/pod_man_reproducible_date - http://bugs.debian.org/759
405 Support POD_MAN_DATE in Pod::Man for the left-hand footer
    DEBPKG:debian/locale-robustness - http://bugs.debian.org/782068
[perl #124310] Make t/run/locale.t survive missing locales masked by
LC_ALL
    DEBPKG:fixes/podman-utc - http://bugs.debian.org/780259 Make the
embedded date from Pod::Man reproducible
    DEBPKG:fixes/podman-utc-docs - http://bugs.debian.org/780259
Documentation and test suite updates for UTC fix
    DEBPKG:fixes/podman-empty-date - http://bugs.debian.org/780259
Support an empty POD_MAN_DATE environment variable
    DEBPKG:fixes/podman-pipe - http://bugs.debian.org/777405 Better
errors for man pages from standard input
    DEBPKG:debian/pod2man-customized - Update porting/customized.dat
for pod2man modifications
    DEBPKG:debian/makemaker-manext - http://bugs.debian.org/247370 Make
EU::MakeMaker honour MANnEXT settings in generated manpage headers
    DEBPKG:debian/makemaker_customized - Update
t/porting/customized.dat for files patched in Debian
    DEBPKG:debian/do-not-record-build-date - [6baa8db] http://bugs.debi
an.org/774422 [perl #125830] Allow overriding the compile time in "perl
-V" output
    DEBPKG:fixes/podman-source-date-epoch - http://bugs.debian.org/8016
21 Make Pod::Man honor the SOURCE_DATE_EPOCH environment variable
    DEBPKG:fixes/podman-source-date-epoch-cleanups - http://bugs.debian
.org/801621 Coding style and documentation for SOURCE_EPOCH_DATE
    DEBPKG:fixes/podman-source-date-epoch-testfix - http://bugs.debian.
org/807086 Guard for building with SOURCE_DATE_EPOCH or POD_MAN_DATE
set
    DEBPKG:debian/devel-ppport-reproducibility - http://bugs.debian.org
/801523 Sort the list of XS code files when generating RealPPPort.xs
    DEBPKG:fixes/encode-unicode-bom - http://bugs.debian.org/798727
[rt.cpan.org #107043] Address
https://rt.cpan.org/Public/Bug/Display.html?id=107043
    DEBPKG:debian/encode-unicode-bom-doc - http://bugs.debian.org/79872
7 Document Debian backport of Encode::Unicode fix
    DEBPKG:debian/kfreebsd-softupdates - http://bugs.debian.org/796798
Work around Debian Bug#796798
    DEBPKG:fixes/autodie-scope - http://bugs.debian.org/798096 Fix a
scoping issue with "no autodie" and the "system" sub
    DEBPKG:debian/debugperl-compat-fix - [perl #127212] http://bugs.deb
ian.org/810326 Disable PERL_TRACK_MEMPOOL for debugging builds
    DEBPKG:fixes/CVE-2015-8607_file_spec_taint_fix - http://bugs.debian
.org/810719 [perl #126862] ensure File::Spec::canonpath() preserves
taint
    DEBPKG:fixes/mkstemp-umask - http://bugs.debian.org/810924 [perl
#127322] [e57270b] Fix umask for mkstemp(3) calls
    DEBPKG:fixes/crosscompile-no-targethost - [perl #127234] Fix the
Configure escape with usecrosscompile but no targethost
    DEBPKG:fixes/podlators-no-encode - [rt.cpan.org #111156] Degrade
gracefully if utf8 is requested but Encode is not available
    DEBPKG:debian/cross-time-hires - [rt.cpan.org #111391] Add an
environment variable to skip running configuration probes
    DEBPKG:fixes/encode-unicode-pod - Unicode.pm: Fix POD error
    DEBPKG:fixes/memoize-pod - [rt.cpan.org #89441] Fix POD errors in
Memoize
    DEBPKG:fixes/ok-pod - Added encoding for pod.
    DEBPKG:fixes/CVE-2016-2381_duplicate_env - remove duplicate
environment variables from environ


@INC for perl 5.22.1:
    /etc/perl
    /usr/local/lib/x86_64-linux-gnu/perl/5.22.1
    /usr/local/share/perl/5.22.1
    /usr/lib/x86_64-linux-gnu/perl5/5.22
    /usr/share/perl5
    /usr/lib/x86_64-linux-gnu/perl/5.22
    /usr/share/perl/5.22
    /usr/local/lib/site_perl
    /usr/lib/x86_64-linux-gnu/perl-base
    .


Environment for perl 5.22.1:
    HOME=/home/jd
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/jd/.gems/bin:/home/jd/bin:/home/jd/bin:/usr/local/bin:/u
sr/bin:/bin:/usr/local/games:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 18, 2016

From @lightsey

0001-Add-blacklist-and-whitelist-support-to-Locale-Makete.patch
From 1429085edd6dde7f605b27094ae03ae5bfe54b5a Mon Sep 17 00:00:00 2001
From: John Lightsey <jd@cpanel.net>
Date: Thu, 17 Mar 2016 16:06:09 +0000
Subject: [PATCH] Add blacklist and whitelist support to Locale::Maketext.

Format string attacks against Locale::Maketext have been discovered in
several popular web applications and addresed by pre-filtering maketext
strings before they are fed into the maketext() method. It is now
possible to restrict the allowed bracked notation methods directly in
Maketext.

This commit also introduces a default blacklist that prevents using the
object and class methods in the Locale::Maketext namespace that were not
intended as bracked notation methods.
---
 dist/Locale-Maketext/lib/Locale/Maketext.pm  | 71 +++++++++++++++++---
 dist/Locale-Maketext/lib/Locale/Maketext.pod | 71 ++++++++++++++++++++
 dist/Locale-Maketext/t/92_blacklist.t        | 93 +++++++++++++++++++++++++++
 dist/Locale-Maketext/t/93_whitelist.t        | 96 ++++++++++++++++++++++++++++
 4 files changed, 322 insertions(+), 9 deletions(-)
 create mode 100644 dist/Locale-Maketext/t/92_blacklist.t
 create mode 100644 dist/Locale-Maketext/t/93_whitelist.t

diff --git a/dist/Locale-Maketext/lib/Locale/Maketext.pm b/dist/Locale-Maketext/lib/Locale/Maketext.pm
index 24c31ea..f213c74 100644
--- a/dist/Locale-Maketext/lib/Locale/Maketext.pm
+++ b/dist/Locale-Maketext/lib/Locale/Maketext.pm
@@ -1,4 +1,3 @@
-
 package Locale::Maketext;
 use strict;
 use vars qw( @ISA $VERSION $MATCH_SUPERS $USING_LANGUAGE_TAGS
@@ -138,6 +137,56 @@ sub fail_with { # an actual attribute method!
 
 #--------------------------------------------------------------------------
 
+sub blacklist {
+    my ( $handle, @methods ) = @_;
+
+    unless ( defined $handle->{'blacklist'} ) {
+        no strict 'refs';
+
+        # Don't let people call methods they're not supposed to from maketext.
+        # Explicitly exclude all methods in this package that start with an
+        # underscore on principle.
+        $handle->{'blacklist'} = {
+            map { $_ => 1 } (
+                qw/
+                  blacklist
+                  encoding
+                  fail_with
+                  failure_handler_auto
+                  fallback_language_classes
+                  fallback_languages
+                  get_handle
+                  init
+                  language_tag
+                  maketext
+                  new
+                  whitelist
+                  /, grep { /^_/ } keys %{ __PACKAGE__ . "::" }
+            ),
+        };
+    }
+
+    if ( scalar @methods ) {
+        $handle->{'blacklist'} = { %{ $handle->{'blacklist'} }, map { $_ => 1 } @methods };
+    }
+
+    delete $handle->{'_external_lex_cache'};
+    return;
+}
+
+sub whitelist {
+    my ( $handle, @methods ) = @_;
+    if ( scalar @methods ) {
+        $handle->{'whitelist'} = {} unless defined $handle->{'whitelist'};
+        $handle->{'whitelist'} = { %{ $handle->{'whitelist'} }, map { $_ => 1 } @methods };
+    }
+
+    delete $handle->{'_external_lex_cache'};
+    return;
+}
+
+#--------------------------------------------------------------------------
+
 sub failure_handler_auto {
     # Meant to be used like:
     #  $handle->fail_with('failure_handler_auto')
@@ -179,6 +228,7 @@ sub new {
     # Nothing fancy!
     my $class = ref($_[0]) || $_[0];
     my $handle = bless {}, $class;
+    $handle->blacklist;
     $handle->init;
     return $handle;
 }
@@ -508,7 +558,7 @@ sub _compile {
     # on strings that don't need compiling.
     return \"$string_to_compile" if($string_to_compile !~ m/[\[~\]]/ms); # return a string ref if chars [~] are not in the string
 
-    my $target = ref($_[0]) || $_[0];
+    my $handle = $_[0];
 
     my(@code);
     my(@c) = (''); # "chunks" -- scratch.
@@ -540,10 +590,10 @@ sub _compile {
                 #  preceding literal.
                 if($in_group) {
                     if($1 eq '') {
-                        $target->_die_pointing($string_to_compile, 'Unterminated bracket group');
+                        $handle->_die_pointing($string_to_compile, 'Unterminated bracket group');
                     }
                     else {
-                        $target->_die_pointing($string_to_compile, 'You can\'t nest bracket groups');
+                        $handle->_die_pointing($string_to_compile, 'You can\'t nest bracket groups');
                     }
                 }
                 else {
@@ -627,13 +677,15 @@ sub _compile {
                         push @code, ' (';
                     }
                     elsif($m =~ /^\w+$/s
-                        # exclude anything fancy, especially fully-qualified module names
+                        && !$handle->{'blacklist'}{$m}
+                        && ( !defined $handle->{'whitelist'} || $handle->{'whitelist'}{$m} )
+                        # exclude anything fancy and restrict to the whitelist/blacklist.
                     ) {
                         push @code, ' $_[0]->' . $m . '(';
                     }
                     else {
                         # TODO: implement something?  or just too icky to consider?
-                        $target->_die_pointing(
+                        $handle->_die_pointing(
                             $string_to_compile,
                             "Can't use \"$m\" as a method name in bracket group",
                             2 + length($c[-1])
@@ -675,7 +727,7 @@ sub _compile {
                     push @c, '';
                 }
                 else {
-                    $target->_die_pointing($string_to_compile, q{Unbalanced ']'});
+                    $handle->_die_pointing($string_to_compile, q{Unbalanced ']'});
                 }
 
             }
@@ -760,8 +812,9 @@ sub _compile {
 
 sub _die_pointing {
     # This is used by _compile to throw a fatal error
-    my $target = shift; # class name
-    # ...leaving $_[0] the error-causing text, and $_[1] the error message
+    my $target = shift;
+    $target = ref($target) || $target; # class name
+                                       # ...leaving $_[0] the error-causing text, and $_[1] the error message
 
     my $i = index($_[0], "\n");
 
diff --git a/dist/Locale-Maketext/lib/Locale/Maketext.pod b/dist/Locale-Maketext/lib/Locale/Maketext.pod
index a391b29..8c5be19 100644
--- a/dist/Locale-Maketext/lib/Locale/Maketext.pod
+++ b/dist/Locale-Maketext/lib/Locale/Maketext.pod
@@ -307,6 +307,13 @@ interested in hearing about it.)
 These two methods are discussed in the section "Controlling
 Lookup Failure".
 
+=item $lh->blacklist(@list)
+
+=item $lh->whitelist(@list)
+
+These methods are discussed in the section "Bracket Notation
+Security".
+
 =back
 
 =head2 Utility Methods
@@ -861,6 +868,70 @@ I do not anticipate that you will need (or particularly want)
 to nest bracket groups, but you are welcome to email me with
 convincing (real-life) arguments to the contrary.
 
+=head1 BRACKET NOTATION SECURITY
+
+Locale::Maketext does not use any special syntax to differentiate
+bracket notation methods from normal class or object methods. This
+design makes it vulnerable to format string attacks whenever it is
+used to process strings provided by untrusted users.
+
+Locale::Maketext does support blacklist and whitelist functionality
+to limit which methods may be called as bracket notation methods.
+
+By default, Locale::Maketext blacklists all methods in the
+Locale::Maketext namespace that begin with the '_' character,
+and all methods which include Perl's namespace separator characters.
+
+The default blacklist for Locale::Maketext also prevents use of the
+following methods in bracket notation:
+
+  blacklist
+  encoding
+  fail_with
+  failure_handler_auto
+  fallback_language_classes
+  fallback_languages
+  get_handle
+  init
+  language_tag
+  maketext
+  new
+  whitelist
+
+This list can be extended by either blacklisting additional "known bad"
+methods, or whitelisting only "known good" methods.
+
+To prevent specific methods from being called in bracket notation, use
+the blacklist() method:
+
+  my $lh = MyProgram::L10N->get_handle();
+  $lh->blacklist(qw{my_internal_method my_other_method});
+  $lh->maketext('[my_internal_method]'); # dies
+
+To limit the allowed bracked notation methods to a specific list, use the
+whitelist() method:
+
+  my $lh = MyProgram::L10N->get_handle();
+  $lh->whitelist('numerate', 'numf');
+  $lh->maketext('[_1] [numerate, _1,shoe,shoes]', 12); # works
+  $lh->maketext('[my_internal_method]'); # dies
+
+The blacklist() and whitelist() methods extend their internal lists
+whenever they are called. To reset the blacklist or whitelist, create
+a new maketext object.
+
+  my $lh = MyProgram::L10N->get_handle();
+  $lh->blacklist('numerate');
+  $lh->blacklist('numf');
+  $lh->maketext('[_1] [numerate,_1,shoe,shoes]', 12); # dies
+
+For lexicons that use an internal cache, translations which have already
+been cached in their compiled form are not affected by subsequent changes
+to the whitelist or blacklist settings. Lexicons that use an external
+cache will have their cache cleared whenever the whitelist of blacklist
+setings change.  The difference between the two types of caching is explained
+in the "Readonly Lexicons" section.
+
 =head1 AUTO LEXICONS
 
 If maketext goes to look in an individual %Lexicon for an entry
diff --git a/dist/Locale-Maketext/t/92_blacklist.t b/dist/Locale-Maketext/t/92_blacklist.t
new file mode 100644
index 0000000..6ed36d1
--- /dev/null
+++ b/dist/Locale-Maketext/t/92_blacklist.t
@@ -0,0 +1,93 @@
+#!/usr/bin/perl -Tw
+
+use strict;
+use warnings;
+use Test::More tests => 17;
+
+BEGIN {
+    use_ok("Locale::Maketext");
+}
+
+{
+
+    package MyTestLocale;
+    no warnings 'once';
+
+    @MyTestLocale::ISA     = qw(Locale::Maketext);
+    %MyTestLocale::Lexicon = ();
+}
+
+{
+
+    package MyTestLocale::en;
+    no warnings 'once';
+
+    @MyTestLocale::en::ISA = qw(MyTestLocale);
+
+    %MyTestLocale::en::Lexicon = ( '_AUTO' => 1 );
+
+    sub custom_handler {
+        return "custom_handler_response";
+    }
+
+    sub _internal_method {
+        return "_internal_method_response";
+    }
+
+    sub new {
+        my ( $class, @args ) = @_;
+        my $lh = $class->SUPER::new(@args);
+        $lh->{use_external_lex_cache} = 1;
+        return $lh;
+    }
+}
+
+my $lh = MyTestLocale->get_handle('en');
+my $res;
+
+# get_handle blocked by default
+$res = eval { $lh->maketext('[get_handle,en]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'get_handle blocked in bracket notation by default blacklist' );
+
+# _ambient_langprefs blocked by default
+$res = eval { $lh->maketext('[_ambient_langprefs]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, '_ambient_langprefs blocked in bracket notation by default blacklist' );
+
+# _internal_method not blocked by default
+$res = eval { $lh->maketext('[_internal_method]') };
+is( $res, "_internal_method_response", '_internal_method allowed in bracket notation by default blacklist' );
+is( $@, '', 'no exception thrown by use of _internal_method under default blacklist' );
+
+# sprintf not blocked by default
+$res = eval { $lh->maketext('[sprintf,%s,hello]') };
+is( $res, "hello", 'sprintf allowed in bracket notation by default blacklist' );
+is( $@,   '',      'no exception thrown by use of sprintf under default blacklist' );
+
+# blacklisting sprintf and numerate
+$lh->blacklist( 'sprintf', 'numerate' );
+
+# sprintf blocked by custom blacklist
+$res = eval { $lh->maketext('[sprintf,%s,hello]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'sprintf blocked in bracket notation by custom blacklist' );
+
+# blacklisting numf and _internal_method
+$lh->blacklist('numf');
+$lh->blacklist('_internal_method');
+
+# sprintf blocked by custom blacklist
+$res = eval { $lh->maketext('[sprintf,%s,hello]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'sprintf blocked in bracket notation by custom blacklist after extension of blacklist' );
+
+# _internal_method blocked by custom blacklist
+$res = eval { $lh->maketext('[_internal_method]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'sprintf blocked in bracket notation by custom blacklist after extension of blacklist' );
+
+# custom_handler not in default or custom blacklist
+$res = eval { $lh->maketext('[custom_handler]') };
+is( $res, "custom_handler_response", 'custom_handler allowed in bracket notation by default and custom blacklists' );
+is( $@, '', 'no exception thrown by use of custom_handler under default and custom blacklists' );
diff --git a/dist/Locale-Maketext/t/93_whitelist.t b/dist/Locale-Maketext/t/93_whitelist.t
new file mode 100644
index 0000000..21f2d85
--- /dev/null
+++ b/dist/Locale-Maketext/t/93_whitelist.t
@@ -0,0 +1,96 @@
+#!/usr/bin/perl -Tw
+
+use strict;
+use warnings;
+use Test::More tests => 17;
+
+BEGIN {
+    use_ok("Locale::Maketext");
+}
+
+{
+
+    package MyTestLocale;
+    no warnings 'once';
+
+    @MyTestLocale::ISA     = qw(Locale::Maketext);
+    %MyTestLocale::Lexicon = ();
+}
+
+{
+
+    package MyTestLocale::en;
+    no warnings 'once';
+
+    @MyTestLocale::en::ISA = qw(MyTestLocale);
+
+    %MyTestLocale::en::Lexicon = ( '_AUTO' => 1 );
+
+    sub custom_handler {
+        return "custom_handler_response";
+    }
+
+    sub _internal_method {
+        return "_internal_method_response";
+    }
+
+    sub new {
+        my ( $class, @args ) = @_;
+        my $lh = $class->SUPER::new(@args);
+        $lh->{use_external_lex_cache} = 1;
+        return $lh;
+    }
+}
+
+my $lh = MyTestLocale->get_handle('en');
+my $res;
+
+# _internal_method not blocked by default
+$res = eval { $lh->maketext('[_internal_method]') };
+is( $res, "_internal_method_response", '_internal_method allowed when no whitelist defined' );
+is( $@, '', 'no exception thrown by use of _internal_method without whitelist setting' );
+
+# whitelisting sprintf
+$lh->whitelist('sprintf');
+
+# _internal_method blocked by whitelist
+$res = eval { $lh->maketext('[_internal_method]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, '_internal_method blocked in bracket notation by whitelist' );
+
+# sprintf allowed by whitelist
+$res = eval { $lh->maketext('[sprintf,%s,hello]') };
+is( $res, "hello", 'sprintf allowed in bracket notation by whitelist' );
+is( $@,   '',      'no exception thrown by use of sprintf with whitelist' );
+
+# custom_handler blocked by whitelist
+$res = eval { $lh->maketext('[custom_handler]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'custom_handler blocked in bracket notation by whitelist' );
+
+# adding custom_handler to whitelist
+$lh->whitelist('custom_handler');
+
+# sprintf still allowed by whitelist
+$res = eval { $lh->maketext('[sprintf,%s,hello]') };
+is( $res, "hello", 'sprintf allowed in bracket notation by whitelist' );
+is( $@,   '',      'no exception thrown by use of sprintf with whitelist' );
+
+# custom_handler allowed by whitelist
+$res = eval { $lh->maketext('[custom_handler]') };
+is( $res, "custom_handler_response", 'custom_handler allowed in bracket notation by whitelist' );
+is( $@, '', 'no exception thrown by use of custom_handler with whitelist' );
+
+# _internal_method blocked by whitelist
+$res = eval { $lh->maketext('[_internal_method]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, '_internal_method blocked in bracket notation by whitelist' );
+
+# adding fail_with to whitelist
+$lh->whitelist('fail_with');
+
+# fail_with still blocked by blacklist
+$res = eval { $lh->maketext('[fail_with,xyzzy]') };
+is( $res, undef, 'no return value from blocked expansion' );
+like( $@, qr/Can't use .* as a method name/, 'fail_with blocked in bracket notation by blacklist even when whitelisted' );
+
-- 
2.7.1

@p5pRT
Copy link
Author

p5pRT commented Apr 20, 2016

From @tonycoz

On Mon Apr 18 11​:11​:27 2016, john@​nixnuts.net wrote​:

The patch attached to this bug report adds support for blacklist
and whitelist functionality directly to Locale​::Maketext.

Webapps that use Locale​::Maketext tend to pre-filter maketext
strings to limit the types of bracket notation that are allowed.
By rolling this directly into Locale​::Maketext, they can limit
the availailable bracket notation methods in a simpler and more
efficient fashion.

I plan to apply this along with the fixes needed to pass the porting tests after 5.24 is releases.

I'll also add a note that clarifies the priority of the black and white lists, per the attached.

Tony

@p5pRT
Copy link
Author

p5pRT commented Apr 20, 2016

From @tonycoz

0002-perl-127923-pass-porting-tests.patch
From 7666a3db2882281360faf15df656c8541e00dd50 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 20 Apr 2016 16:27:09 +1000
Subject: (perl #127923) pass porting tests

- update MANIFEST, AUTHORS
- bump $Locale::Maketext::VERSION
---
 AUTHORS                                     | 1 +
 MANIFEST                                    | 2 ++
 dist/Locale-Maketext/lib/Locale/Maketext.pm | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/AUTHORS b/AUTHORS
index 3cc2ef1..167efd9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -620,6 +620,7 @@ John Holdsworth			<coldwave@bigfoot.com>
 John Hughes			<john@AtlanTech.COM>
 John Kristian			<jmk2001@engineer.com>
 John L. Allen			<allen@grumman.com>
+John Lightsey			<jd@cpanel.net>
 John Macdonald			<jmm@revenge.elegant.com>
 John Malmberg			<wb8tyw@gmail.com>
 John Nolan			<jpnolan@Op.Net>
diff --git a/MANIFEST b/MANIFEST
index 3da3119..eafece8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -3264,6 +3264,8 @@ dist/Locale-Maketext/t/60_super.t			See if Locale::Maketext works
 dist/Locale-Maketext/t/70_fail_auto.t			See if Locale::Maketext works
 dist/Locale-Maketext/t/90_utf8.t			See if Locale::Maketext works
 dist/Locale-Maketext/t/91_backslash.t			See if Locale::Maketext works
+dist/Locale-Maketext/t/92_blacklist.t			See if Locale::Maketext works
+dist/Locale-Maketext/t/93_whitelist.t			See if Locale::Maketext works
 dist/Module-CoreList/Changes			Module::CoreList Changes
 dist/Module-CoreList/corelist			The corelist command-line utility
 dist/Module-CoreList/identify-dependencies	A usage example for Module::CoreList
diff --git a/dist/Locale-Maketext/lib/Locale/Maketext.pm b/dist/Locale-Maketext/lib/Locale/Maketext.pm
index f213c74..823c8d7 100644
--- a/dist/Locale-Maketext/lib/Locale/Maketext.pm
+++ b/dist/Locale-Maketext/lib/Locale/Maketext.pm
@@ -26,7 +26,7 @@ BEGIN {
 }
 
 
-$VERSION = '1.26';
+$VERSION = '1.27';
 @ISA = ();
 
 $MATCH_SUPERS = 1;
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Apr 20, 2016

From @tonycoz

0003-perl-127923-note-priority-between-the-white-and-blac.patch
From 7d7310252826cac426f75cca1e8780bbdbb1bcd8 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 20 Apr 2016 16:30:05 +1000
Subject: (perl #127923) note priority between the white and blacklist

---
 dist/Locale-Maketext/lib/Locale/Maketext.pod | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dist/Locale-Maketext/lib/Locale/Maketext.pod b/dist/Locale-Maketext/lib/Locale/Maketext.pod
index 8c5be19..564e5af 100644
--- a/dist/Locale-Maketext/lib/Locale/Maketext.pod
+++ b/dist/Locale-Maketext/lib/Locale/Maketext.pod
@@ -932,6 +932,9 @@ cache will have their cache cleared whenever the whitelist of blacklist
 setings change.  The difference between the two types of caching is explained
 in the "Readonly Lexicons" section.
 
+Methods disallowed by the blacklist cannot be permitted by the
+whitelist.
+
 =head1 AUTO LEXICONS
 
 If maketext goes to look in an individual %Lexicon for an entry
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Apr 20, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 20, 2016

From @lightsey

On Tue, 2016-04-19 at 23​:33 -0700, Tony Cook via RT wrote​:

On Mon Apr 18 11​:11​:27 2016, john@​nixnuts.net wrote​:

The patch attached to this bug report adds support for blacklist
and whitelist functionality directly to Locale​::Maketext.
 
Webapps that use Locale​::Maketext tend to pre-filter maketext
strings to limit the types of bracket notation that are allowed.
By rolling this directly into Locale​::Maketext, they can limit
the availailable bracket notation methods in a simpler and more
efficient fashion.

I plan to apply this along with the fixes needed to pass the porting
tests after 5.24 is releases.

I'll also add a note that clarifies the priority of the black and
white lists, per the attached.

Excellent, looks good to me.

@p5pRT
Copy link
Author

p5pRT commented Apr 22, 2016

From @toddr

On Tue Apr 19 23​:33​:47 2016, tonyc wrote​:

I plan to apply this along with the fixes needed to pass the porting
tests after 5.24 is releases.

FYI I'm going to wait on this merge before releasing L​:MT to CPAN.

@p5pRT
Copy link
Author

p5pRT commented May 9, 2016

From @toddr

On Fri Apr 22 08​:23​:14 2016, TODDR wrote​:

On Tue Apr 19 23​:33​:47 2016, tonyc wrote​:

I plan to apply this along with the fixes needed to pass the porting
tests after 5.24 is releases.

FYI I'm going to wait on this merge before releasing L​:MT to CPAN.

Bump. Are we ok to merge this now?

Todd

@p5pRT
Copy link
Author

p5pRT commented May 10, 2016

From @tonycoz

On Mon May 09 11​:44​:30 2016, TODDR wrote​:

On Fri Apr 22 08​:23​:14 2016, TODDR wrote​:

On Tue Apr 19 23​:33​:47 2016, tonyc wrote​:

I plan to apply this along with the fixes needed to pass the porting
tests after 5.24 is releases.

FYI I'm going to wait on this merge before releasing L​:MT to CPAN.

Bump. Are we ok to merge this now?

Thanks, applied as 6a810bd, which my fixes as cf6c814 and note as e5000e0.

Tony

@p5pRT
Copy link
Author

p5pRT commented May 10, 2016

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release today of Perl 5.26.0, this and 210 other issues have been
resolved.

Perl 5.26.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.26.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT p5pRT closed this as completed May 30, 2017
@p5pRT
Copy link
Author

p5pRT commented May 30, 2017

@khwilliamson - Status changed from 'pending release' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant