Subject: | @INC does not get set correctly when run in taint mode |
distriubtion: local-lib-1.008004
perl version: 5.10.1
OS: Linux host 2.6.32-40-generic-pae #87-Ubuntu SMP Mon Mar 5 21:44:34 UTC 2012 i686
GNU/Linux
Consider the following:
eval $(perl -Mlocal::lib)
# Run without taint mode
perl -w -MData::Dumper -e 'print Dumper(\@INC)'
# Run with taint mode
perl -wT -MData::Dumper -e 'print Dumper(\@INC)'
The latter version (with taint mode) does not include ~/perl5 directories in @INC (and thus
ignores any modules installed for this local::lib environment). This is because perl
ignores $PERL5LIB in taint mode (man perlrun).
I can't imagine that this use case could be fixed, due to local::lib's reliance on
$PERL5LIB, but it would be nice to call out in the documentation.
There is a similar use case that also has an issue with taint mode that can be fixed,
however:
# Attempt 1, with no local::lib environment
unset PERL_LOCAL_LIB_ROOT PERL_MB_OPT PERL_MM_OPT PERL5LIB
perl -wT -Mlocal::lib -MData::Dumper -e 'print Dumper(\@INC)'
# Attempt 2, with a local::lib environment
eval $(perl -Mlocal::lib)
perl -wT -Mlocal::lib -MData::Dumper -e 'print Dumper(\@INC)'
The first attempt includes ~/perl5 directories in @INC, while the second attempt does not.
This is because local::lib::setup_local_lib_for() returns without taking any actions if it's
asked to add a local::lib path that already exists in the enviornment. In non-taint mode
that works fine, because PERL5LIB is set correctly, but in taint mode we need to explicitly
set @INC.
I've attached a patch and a test that should resolve that issue.
Subject: | 0001-fix-issue-with-taint-mode.patch |
From e1de0102d09b7c30efcb3ad484ed46a1f96aa36c Mon Sep 17 00:00:00 2001
From: Stephen Caldwell <steve@campusexplorer.com>
Date: Wed, 18 Apr 2012 08:24:17 -0700
Subject: [PATCH] fix issue with taint mode
---
lib/local/lib.pm | 8 ++++++--
t/taint-mode.t | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 2 deletions(-)
create mode 100644 t/taint-mode.t
diff --git a/lib/local/lib.pm b/lib/local/lib.pm
index 5632832..3cd608d 100644
--- a/lib/local/lib.pm
+++ b/lib/local/lib.pm
@@ -209,10 +209,12 @@ sub setup_local_lib_for {
$path = $class->ensure_dir_structure_for($path);
+ my $no_additions = 0;
+
if (! $deactivating) {
if (@active_lls && $active_lls[-1] eq $path) {
exit 0 if $0 eq '-';
- return; # Asked to add what's already at the top of the stack
+ $no_additions = 1; # Asked to add what's already at the top of the stack
} elsif (grep { $_ eq $path} @active_lls) {
# Asked to add a dir that's lower in the stack -- so we remove it from
# where it is, and then add it back at the top.
@@ -227,7 +229,9 @@ sub setup_local_lib_for {
$class->print_environment_vars_for($path, $deactivating, $interpolate);
exit 0;
} else {
- $class->setup_env_hash_for($path, $deactivating);
+ unless ($no_additions) {
+ $class->setup_env_hash_for($path, $deactivating);
+ }
@INC = _uniq(split($Config{path_sep}, $ENV{PERL5LIB}), @INC);
}
}
diff --git a/t/taint-mode.t b/t/taint-mode.t
new file mode 100644
index 0000000..68e1bb1
--- /dev/null
+++ b/t/taint-mode.t
@@ -0,0 +1,43 @@
+#
+# t/taint-mode.t: checks that local::lib sets up @INC correctly when
+# included in a script that has taint mode on, and is executing in an
+# environment in which local::lib has already been loaded.
+#
+
+use strict;
+use warnings;
+use Test::More;
+use File::Temp qw(tempdir tempfile);
+use Cwd;
+
+plan tests => 1;
+
+# Setup temp dir to serve as local lib
+my $dir1 = tempdir('test_local_lib-XXXXX', DIR => Cwd::abs_path('t'), CLEANUP => 1);
+
+# Setup local::lib environment using our temp dir
+use local::lib ();
+local::lib->import($dir1);
+
+# Create a script that has taint mode turned on, and tries to use a
+# local lib to the same temp dir.
+my ($fh, $filename) = tempfile('test_local_lib-XXXXX', DIR => Cwd::abs_path('t'), UNLINK => 1);
+
+print $fh <<EOM;
+#!/usr/bin/perl -T
+use local::lib '$dir1';
+my \$dir1 = "$dir1";
+if (grep { \$_ =~ m{^\$dir1/} } \@INC) {
+ exit 0;
+}
+exit 1
+EOM
+close $fh;
+
+# Execute the script and check return value.
+# NOTE: a bit of a hack below with the -I switch to make sure that the
+# script is executing with the same path as this test script.
+my $exit_val = system('perl', '-I', Cwd::abs_path('blib/lib'), '-T', $filename);
+$exit_val = $exit_val >> 8;
+
+is($exit_val, 0, 'test script exited with 0, local::lib dir found in @INC');
--
1.7.10