xslate / p5-Mouse

Lightweight class builder for Perl, as a subset of Moose
https://metacpan.org/release/Mouse
Other
46 stars 32 forks source link

Crashing when attributes number exceeds 23 #64

Closed serhiybutz closed 7 years ago

serhiybutz commented 7 years ago

Under Ubuntu 16.04, Perl 5.22.1 (5.24.0 too) following scripts combination crashes:

File: Bar.pm

package Bar;
use Mouse;
has attr00  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr01  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr02  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr03  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr04  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr05  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr06  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr07  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr08  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr09  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr10  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr11  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr12  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr13  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr14  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr15  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr16  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr17  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr18  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr19  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr20  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr21  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr22  => (
    is       => 'ro',
    isa      => 'Str',
);
has attr23  => (
    is       => 'ro',
    isa      => 'Str',
);
1;

File: Foo.pm

package Foo;
use Mouse;
extends 'Bar';
has '+attr00'  => (
    isa => 'Str',
);
1;

File: Holder.pm

package Holder;
use Foo;
1;

File: run.pl

#!/usr/local/bin/perl -w
use warnings;
use Holder;

When script run.pl is run it crashes with following error message (sometimes it goes with backtrace):

Could not find an attribute by the name of 'attr00' to inherit from in Foo at /usr/local/lib/perl5/site_perl/5.24.0/x86_64-linux/Mouse/Meta/Class.pm line 225.
    Mouse::Meta::Class::add_attribute(Mouse::Meta::Class=HASH(0x16a2d20), "+attr00", "isa", "Str") called at /usr/local/lib/perl5/site_perl/5.24.0/x86_64-linux/Mouse.pm line 52
    Mouse::has("+attr00", "isa", "Str") called at Foo.pm line 4
    require Foo.pm called at Holder.pm line 2
    Holder::BEGIN() called at Foo.pm line 0
    eval {...} called at Foo.pm line 0
    require Holder.pm called at ./run.pl line 3
    main::BEGIN() called at Foo.pm line 0
    eval {...} called at Foo.pm line 0
Compilation failed in require at Holder.pm line 2.
BEGIN failed--compilation aborted at Holder.pm line 2.
Compilation failed in require at ./run.pl line 3.
BEGIN failed--compilation aborted at ./run.pl line 3.

Crashing stops if: 1) 'use warnings' in run.pl is removed 2) number of attributes in Bar.pm is less than 24 3) run in debug-mode (like perl -d run.pl)

Also here's a fragment of valgrind output that I believe is relevant to the issue:

==22649== Invalid write of size 8
==22649==    at 0x6AA1CC0: XS_Mouse__Meta__Class_get_all_attributes (in /usr/local/lib/perl5/site_perl/5.24.0/x86_64-linux/auto/Mouse/Mouse.so)
==22649==    by 0x4B5887: Perl_pp_entersub (in /usr/local/bin/perl)
sezal commented 7 years ago

Is there any update on this issue? Because of this issue we have to keep our production servers running on ubuntu trusty :(

syohex commented 7 years ago

Sorry belated response. I can reproduce this issue.

I suppose stack pointer is strange if there are more than 22 attributes and then Mouse::Meta::Class::get_all_attributes method returns nothing(It should returns 23 attribute instances). However I cannot understand how to fix this issue.

(Why does it work if its method is called two times ?)

diff --git a/lib/Mouse/Meta/Class.pm b/lib/Mouse/Meta/Class.pm
index 4c1c5f3..4b94db9 100644
--- a/lib/Mouse/Meta/Class.pm
+++ b/lib/Mouse/Meta/Class.pm
@@ -193,6 +193,7 @@ sub find_attribute_by_name {
     my($self, $name) = @_;
     defined($name)
         or $self->throw_error('You must define an attribute name to find');
+    $self->get_all_attributes;
     foreach my $attr($self->get_all_attributes) {
         return $attr if $attr->name eq $name;
     }
sezal commented 7 years ago

we have submitted #67 to fix this issue.

sezal commented 7 years ago

update: patch was tested for more than a week on production and everything works smooth now.

syohex commented 7 years ago

Release Mouse v2.4.7 which applies #67 workaround.