@@ -6,6 +6,11 @@ use vars qw($VERSION);
6
6
$VERSION = ' 2.23' ;
7
7
$VERSION =~ tr / _// d;
8
8
9
+ # simplest way to avoid indexing of the package: no package statement
10
+ sub base ::__inc::unhook { @INC = grep !(ref eq ' CODE' && $_ == $_ [0]), @INC }
11
+ # instance is blessed array of coderefs to be removed from @INC at scope exit
12
+ sub base ::__inc::scope_guard::DESTROY { base::__inc::unhook $_ for @{$_ [0]} }
13
+
9
14
# constant.pm is slow
10
15
sub SUCCESS () { 1 }
11
16
@@ -91,13 +96,59 @@ sub import {
91
96
92
97
next if grep $_ -> isa($base ), ($inheritor , @bases );
93
98
94
- # Following blocks help isolate $SIG{__DIE__} changes
99
+ # Following blocks help isolate $SIG{__DIE__} and @INC changes
95
100
{
96
101
my $sigdie ;
97
102
{
98
103
local $SIG {__DIE__ };
99
104
my $fn = _module_to_filename($base );
100
- eval { require $fn };
105
+ my $dot_hidden ;
106
+ eval {
107
+ my $guard ;
108
+ if ($INC [-1] eq ' .' && %{" $base \: :" }) {
109
+ # So: the package already exists => this an optional load
110
+ # And: there is a dot at the end of @INC => we want to hide it
111
+ # However: we only want to hide it during our *own* require()
112
+ # (i.e. without affecting nested require()s).
113
+ # So we add a hook to @INC whose job is to hide the dot, but which
114
+ # first checks checks the callstack depth, because within nested
115
+ # require()s the callstack is deeper.
116
+ # Since CORE::GLOBAL::require makes it unknowable in advance what
117
+ # the exact relevant callstack depth will be, we have to record it
118
+ # inside a hook. So we put another hook just for that at the front
119
+ # of @INC, where it's guaranteed to run -- immediately.
120
+ # The dot-hiding hook does its job by sitting directly in front of
121
+ # the dot and removing itself from @INC when reached. This causes
122
+ # the dot to move up one index in @INC, causing the loop inside
123
+ # pp_require() to skip it.
124
+ # Loaded coded may disturb this precise arrangement, but that's OK
125
+ # because the hook is inert by that time. It is only active during
126
+ # the top-level require(), when @INC is in our control. The only
127
+ # possible gotcha is if other hooks already in @INC modify @INC in
128
+ # some way during that initial require().
129
+ # Note that this jiggery hookery works just fine recursively: if
130
+ # a module loaded via base.pm uses base.pm itself, there will be
131
+ # one pair of hooks in @INC per base::import call frame, but the
132
+ # pairs from different nestings do not interfere with each other.
133
+ my $lvl ;
134
+ unshift @INC , sub { return if defined $lvl ; 1 while defined caller ++$lvl ; () };
135
+ splice @INC , -1, 0, sub { return if defined caller $lvl ; ++$dot_hidden , &base::__inc::unhook; () };
136
+ $guard = bless [ @INC [0,-2] ], ' base::__inc::scope_guard' ;
137
+ }
138
+ require $fn
139
+ };
140
+ if ($dot_hidden && (my @fn = grep -e && !( -d _ || -b _ ), $fn .' c' , $fn )) {
141
+ require Carp;
142
+ Carp::croak(<<ERROR );
143
+ Base class package "$base " is not empty but "$fn [0]" exists in the current directory.
144
+ To help avoid security issues, base.pm now refuses to load optional modules
145
+ from the current working directory when it is the last entry in \@ INC.
146
+ If your software worked on previous versions of Perl, the best solution
147
+ is to use FindBin to detect the path properly and to add that path to
148
+ \@ INC. As a last resort, you can re-enable looking in the current working
149
+ directory by adding "use lib '.'" to your code.
150
+ ERROR
151
+ }
101
152
# Only ignore "Can't locate" errors from our eval require.
102
153
# Other fatal errors (syntax etc) must be reported.
103
154
#
0 commit comments