Subject: | Deep recursion on String Overloaded object [TEST and PATCH] |
If UNIVERSAL::can is invoked through an overloaded stringification of an
object, it causes a Deep recursion, and eventually segfaults (tested on
perl 5.10).
This seems to be due to UNIVERSAL::can calling UNIVERSAL::isa and
UNIVERSAL::isa calling back to UNIVERSAL::can in this circumstance.
I am unsure if this bug is related at all to bug #47326 for
UNIVERSAL::isa.
https://rt.cpan.org/Ticket/Display.html?id=47326
Attached is a test case demonstrating the problem, and a patch for
resolving it.
My proposed fix is to add local $recursing = 1 before calling $caller-
Show quoted text
>isa($_[0]).
The output of the test case, when broken, is as follows:
$ perl universal_can_deep_recursion.t
1..1
Deep recursion on anonymous subroutine at
/usr/share/perl5/UNIVERSAL/can.pm line 57.
Deep recursion on subroutine "UNIVERSAL::can::can" at
universal_can_deep_recursion.t line 6.
Segmentation fault
Subject: | universal_can_deep_recursion.patch |
--- lib/UNIVERSAL/can.pm 2009-06-22 16:42:08.000000000 -0400
+++ lib/UNIVERSAL/can.pm 2009-09-09 16:12:06.000000000 -0400
@@ -40,7 +40,7 @@
goto &$orig if $recursing
|| ( defined $caller
&& defined $_[0]
- && eval { $caller->isa( $_[0] ); } );
+ && eval { local $recursing = 1; $caller->isa($_[0]) } );
# call an overridden can() if it exists
my $can = eval { $_[0]->$orig('can') || 0 };
Subject: | universal_can_deep_recursion.t |
#!/usr/bin/perl
package Test::Overloaded::String;
use strict;
use warnings;
use overload '""' => sub { $_[0]->can('bar') };
sub new { bless {}, shift }
sub bar {1}
1;
package main;
use strict;
use warnings;
use Test::More tests => 1;
use UNIVERSAL::can;
my $foo = Test::Overloaded::String->new;
ok "$foo", "Didn't segfault";