This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
allow sort() reentrancy (variant of patch suggested by
authorGurusamy Sarathy <gsar@cpan.org>
Thu, 27 Apr 2000 20:34:24 +0000 (20:34 +0000)
committerGurusamy Sarathy <gsar@cpan.org>
Thu, 27 Apr 2000 20:34:24 +0000 (20:34 +0000)
Hugo van der Sanden)

p4raw-id: //depot/perl@5975

pp_ctl.c
t/op/sort.t

index 64c706e..2308d35 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -883,15 +883,18 @@ PP(pp_sort)
 
            CATCH_SET(TRUE);
            PUSHSTACKi(PERLSI_SORT);
-           if (PL_sortstash != stash) {
-               PL_firstgv = gv_fetchpv("a", TRUE, SVt_PV);
-               PL_secondgv = gv_fetchpv("b", TRUE, SVt_PV);
-               PL_sortstash = stash;
+           if (!hasargs && !is_xsub) {
+               if (PL_sortstash != stash || !PL_firstgv || !PL_secondgv) {
+                   SAVESPTR(PL_firstgv);
+                   SAVESPTR(PL_secondgv);
+                   PL_firstgv = gv_fetchpv("a", TRUE, SVt_PV);
+                   PL_secondgv = gv_fetchpv("b", TRUE, SVt_PV);
+                   PL_sortstash = stash;
+               }
+               SAVESPTR(GvSV(PL_firstgv));
+               SAVESPTR(GvSV(PL_secondgv));
            }
 
-           SAVESPTR(GvSV(PL_firstgv));
-           SAVESPTR(GvSV(PL_secondgv));
-
            PUSHBLOCK(cx, CXt_NULL, PL_stack_base);
            if (!(PL_op->op_flags & OPf_SPECIAL)) {
                cx->cx_type = CXt_SUB;
index 00b2dac..8161701 100755 (executable)
@@ -5,7 +5,7 @@ BEGIN {
     unshift @INC, '../lib';
 }
 use warnings;
-print "1..55\n";
+print "1..57\n";
 
 # XXX known to leak scalars
 {
@@ -303,3 +303,21 @@ sub cxt_five { sort { test_if_scalar($a,$b); } 1,2 }
 @x = cxt_five();
 sub cxt_six { sort test_if_scalar 1,2 }
 @x = cxt_six();
+
+# test against a reentrancy bug
+{
+    package Bar;
+    sub compare { $a cmp $b }
+    sub reenter { my @force = sort compare qw/a b/ }
+}
+{
+    my($def, $init) = (0, 0);
+    @b = sort {
+       $def = 1 if defined $Bar::a;
+       Bar::reenter() unless $init++;
+       $a <=> $b
+    } qw/4 3 1 2/;
+    print ("@b" eq '1 2 3 4' ? "ok 56\n" : "not ok 56\n");
+    print "# x = '@b'\n";
+    print !$def ? "ok 57\n" : "not ok 57\n";
+}