Skip to content

Commit

Permalink
Insulate DBIC::Carp from rogue can() overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
ribasushi committed Jul 14, 2016
1 parent c40b574 commit 17d4e61
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions lib/DBIx/Class/Carp.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,44 @@ use warnings;
use Carp ();
$Carp::Internal{ (__PACKAGE__) }++;

use Scalar::Util ();

# Because... sigh
# There are cases out there where a user provides a can() that won't actually
# work as perl intends it. Since this is a reporting library, we *have* to be
# extra paranoid ( e.g. https://rt.cpan.org/Ticket/Display.html?id=90715 )
sub __safe_can ($$) {

This comment has been minimized.

Copy link
@ribasushi

ribasushi Jul 14, 2016

Author Collaborator

@kentfredric The final version, if you care to submit it to Safe::Isa

@haarg This may be of interest in super-critical parts of Moo as well (basically when you are going to throw anyway, and the very error generator gets confused). Have not looked whether there are such cases in the codebase, just highlighting you as FYI.

local $@;
local $SIG{__DIE__} if $SIG{__DIE__};

my $cref;
eval {
$cref = $_[0]->can( $_[1] );

# in case the can() isn't an actual UNIVERSAL::can()
die "Return value of $_[0]" . "->can(q($_[1])) is true yet not a code reference...\n"
if $cref and Scalar::Util::reftype($cref) ne 'CODE';

1;
} or do {
undef $cref;

# can not use DBIC::_Util::emit_loud_diag - it uses us internally
printf STDERR
"\n$0: !!! INTERNAL PANIC !!!\nClass '%s' implements or inherits a broken can() - PLEASE FIX ASAP!: %s\n\n",
( length ref $_[0] ? ref $_[0] : $_[0] ),
$@,
;
};

$cref;
}

sub __find_caller {
my ($skip_pattern, $class) = @_;

my $skip_class_data = $class->_skip_namespace_frames
if ($class and $class->can('_skip_namespace_frames'));
if ($class and __safe_can($class, '_skip_namespace_frames') );

$skip_pattern = qr/$skip_pattern|$skip_class_data/
if $skip_class_data;
Expand All @@ -40,7 +73,7 @@ sub __find_caller {
) ? $f[3] : undef;

if (
$f[0]->can('_skip_namespace_frames')
__safe_can( $f[0], '_skip_namespace_frames' )
and
my $extra_skip = $f[0]->_skip_namespace_frames
) {
Expand Down

0 comments on commit 17d4e61

Please sign in to comment.