diff options
-rw-r--r-- | ext/mro/mro.xs | 3 | ||||
-rw-r--r-- | mro.c | 3 | ||||
-rw-r--r-- | t/mro/basic.t | 8 | ||||
-rw-r--r-- | 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 78fa8df0e6..81539b09f6 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 */ @@ -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 65090732f7..5625b5190e 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 dd129cf442..20ae5f09b4 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"; +} |