This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Handle require() on implicit $_ properly w/r global overrides
authorVincent Pit <vince@profvince.com>
Sun, 20 Nov 2011 10:56:11 +0000 (11:56 +0100)
committerVincent Pit <vince@profvince.com>
Sun, 20 Nov 2011 10:56:41 +0000 (11:56 +0100)
Those require() calls are compiled as BASEOPs, so it is invalid to look for
their op_first member when they are translated to a call to the global
override subroutine. The new entersub call should get $_ in its argument
list instead.

This fixes [perl #78260].

op.c
pod/perldelta.pod
t/op/override.t

diff --git a/op.c b/op.c
index 6a6fa87..8727db4 100644 (file)
--- a/op.c
+++ b/op.c
@@ -8588,10 +8588,14 @@ Perl_ck_require(pTHX_ OP *o)
     }
 
     if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) {
-       OP * const kid = cUNOPo->op_first;
-       OP * newop;
-
-       cUNOPo->op_first = 0;
+       OP *kid, *newop;
+       if (o->op_flags & OPf_KIDS) {
+           kid = cUNOPo->op_first;
+           cUNOPo->op_first = NULL;
+       }
+       else {
+           kid = newDEFSVOP();
+       }
 #ifndef PERL_MAD
        op_free(o);
 #endif
index b9e3631..1e6c7ea 100644 (file)
@@ -580,6 +580,12 @@ the warnings would occur if enabled in the comparison routine's scope.
 C<Internals::SvREFCNT> now behaves consistently in 'get' and 'set' scenarios
 [perl #103222] and also treats the reference count as unsigned.
 
+=item *
+
+Calling C<require> on an implicit C<$_> when C<*CORE::GLOBAL::require> has
+been overridden does not segfault anymore, and C<$_> is now passed to the
+overriding subroutine [perl #78260].
+
 =back
 
 =head1 Acknowledgements
index 413ba77..ab2cbf1 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 26;
+plan tests => 28;
 
 #
 # This file tries to test builtin override using CORE::GLOBAL
@@ -52,6 +52,18 @@ is( $r, join($dirsep, "Foo", "Bar.pm") );
 eval "use 5.006";
 is( $r, "5.006" );
 
+{
+    local $_ = 'foo.pm';
+    require;
+    is( $r, 'foo.pm' );
+}
+
+{
+    my $_ = 'bar.pm';
+    require;
+    is( $r, 'bar.pm' );
+}
+
 # localizing *CORE::GLOBAL::foo should revert to finding CORE::foo
 {
     local(*CORE::GLOBAL::require);