Skip Menu |

This queue is for tickets about the UNIVERSAL-can CPAN distribution.

Report information
The Basics
Id: 49580
Status: resolved
Worked: 15 min
Priority: 0/
Queue: UNIVERSAL-can

People
Owner: chromatic [...] cpan.org
Requestors: POSSUM [...] cpan.org
Cc: BOLDRA [...] boldra.org
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.15
Fixed in: (no value)



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";
I also had this problem, cygwin perl 5.10, and POSSUMS patch works well for me.
The bug also bit me working with Test::MockObject under Perl 5.10.0 on Linux. -Mark
I have discovered that my patch does not fix the problem in some cases under perl 5.8.6 (The Deep recursion warning goes away, but it still segfaults). I will attempt to put together a test case when I get a chance.
On Sun Nov 01 18:14:55 2009, MGRIMES wrote: Show quoted text
> The bug also bit me working with Test::MockObject under Perl 5.10.0 on > Linux.
indeed, since test::mockobject is using universal::can. the patch fixes the problem for me on 5.10.1 patched in mandriva package, i'd rather have however a fixed release.
I'm tentatively marking this as resolved in 1.16. I applied the patches as-is; thank you. If this is reproducible in 5.8.6 or earlier, please feel free to reopen.