From 3df5c4b513c5e5c2f25d831f556f2a1c5693ce98 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Sun, 1 Sep 2013 14:47:38 -0700 Subject: [PATCH] Teach mro code about null array elements MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is part of ticket #119433. Commit ce0d49f changed AVs to use NULL for nonexistent elements. The mro lookup code was not accounting for that, causing Class::Contract’s tests to crash (and perhaps other modules, too). --- ext/mro/mro.xs | 3 ++- mro.c | 3 ++- t/mro/basic.t | 8 +++++++- t/mro/isa_c3.t | 7 +++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ext/mro/mro.xs b/ext/mro/mro.xs index 78fa8df..81539b0 100644 --- a/ext/mro/mro.xs +++ b/ext/mro/mro.xs @@ -80,8 +80,9 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level) SSize_t items = AvFILLp(isa) + 1; SV** isa_ptr = AvARRAY(isa); while(items--) { - SV* const isa_item = *isa_ptr++; + SV* const isa_item = *isa_ptr ? *isa_ptr : &PL_sv_undef; HV* const isa_item_stash = gv_stashsv(isa_item, 0); + isa_ptr++; if(!isa_item_stash) { /* if no stash, make a temporary fake MRO containing just itself */ diff --git a/mro.c b/mro.c index 2ce9fa2..18dfa8c 100644 --- a/mro.c +++ b/mro.c @@ -269,10 +269,11 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level) /* foreach(@ISA) */ while (items--) { - SV* const sv = *svp++; + SV* const sv = *svp ? *svp : &PL_sv_undef; HV* const basestash = gv_stashsv(sv, 0); SV *const *subrv_p; I32 subrv_items; + svp++; if (!basestash) { /* if no stash exists for this @ISA member, diff --git a/t/mro/basic.t b/t/mro/basic.t index 6509073..5625b51 100644 --- a/t/mro/basic.t +++ b/t/mro/basic.t @@ -8,7 +8,7 @@ BEGIN { @INC = '../lib'; require q(./test.pl); } -plan(tests => 60); +plan(tests => 61); require mro; @@ -389,3 +389,9 @@ undef $x; # should use the new DESTROY is $destroy_output, "new", 'Changes to UNIVERSAL::DESTROY invalidate DESTROY caches'; undef *UNIVERSAL::DESTROY; + +{ + no warnings 'uninitialized'; + $#_119433::ISA++; + pass "no crash when ISA contains nonexistent elements"; +} diff --git a/t/mro/isa_c3.t b/t/mro/isa_c3.t index dd129cf..20ae5f0 100644 --- a/t/mro/isa_c3.t +++ b/t/mro/isa_c3.t @@ -67,3 +67,10 @@ foreach my $package (qw(klonk urkkk kapow kayo thwacke zzzzzwap whamm)) { object_ok($ref, $class, $package); } } + +package _119433 { + use mro 'c3'; + no warnings 'uninitialized'; + $#_119433::ISA++; + ::pass "no crash when ISA contains nonexistent elements"; +} -- 2.7.4