On Wed, Jul 13, 2005 at 01:40:03PM -0700, Michael G Schwern wrote:
> The problem is the use of goto &foo inside a __WARN__ when &foo also calls
> warn().  I suspect whatever magic that keeps warn() from calling 
> $SIG{__WARN__} when its already inside one is lost.
> 
>   #!/sw/bin/perl -w
> 
>   my $warn = sub { warn(join "\n", caller, @_) };
> 
>   $SIG{__WARN__} = sub {
>       # &$warn;      # this is ok
>       goto &$warn;   # this segfaults
>   };
> 
>   warn "foo";

the disabling of $SIG{__WARN__} was done by cheking the call depth of the
associated sub. The goto &foo ensured that this was always at zero.

The change below fixes this by localsised PL_warnhook t6o zero within a
call to a warn hook.

-- 
Britain, Britain, Britain! Discovered by Sir Henry Britain in
sixteen-oh-ten. Sold to Germany a year later for a pfennig and the promise
of a kiss. Destroyed in eighteen thirty-fourty two, and rebuilt a week
later by a man. This we know. Hello. But what of the people of Britain?
Who they? What do? And why?   -- Little Britain


Change 25160 by [EMAIL PROTECTED] on 2005/07/17 20:12:54

        $SIG{__WARN__} = sub { goto &foo } could recurse infinitely

Affected files ...

... //depot/perl/t/op/goto.t#30 edit
... //depot/perl/util.c#484 edit

Differences ...

==== //depot/perl/t/op/goto.t#30 (xtext) ====

@@ -10,7 +10,7 @@
 
 use warnings;
 use strict;
-plan tests => 56;
+plan tests => 57;
 
 our $foo;
 while ($?) {
@@ -436,3 +436,13 @@
 like($@, qr/Can't goto subroutine from an eval-string/, 'eval string');
 eval { goto &null };
 like($@, qr/Can't goto subroutine from an eval-block/, 'eval block');
+
+# [perl #36521] goto &foo in warn handler could defeat recursion avoider
+
+{
+    my $r = runperl(
+               stderr => 1,
+               prog => 'my $d; my $w = sub { return if $d++; warn q(bar)}; 
local $SIG{__WARN__} = sub { goto &$w; }; warn q(foo);'
+    );
+    like($r, qr/bar/, "goto &foo in warn");
+}

==== //depot/perl/util.c#484 (text) ====

@@ -1278,6 +1278,8 @@
            SV *msg;
 
            ENTER;
+           SAVESPTR(PL_warnhook);
+           PL_warnhook = Nullsv;
            save_re_context();
            msg = newSVpvn(message, msglen);
            SvFLAGS(msg) |= utf8;

Reply via email to