From: Nicholas Clark Date: Sat, 23 Apr 2011 20:07:10 +0000 (+0100) Subject: Fix potential SEGVs for OP_AELEMFAST on a lexical. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=574d9fd949280e15565bdd31f6d7c6b445e4884f;p=p5sagit%2FDevel-Size.git Fix potential SEGVs for OP_AELEMFAST on a lexical. OP_AELEMFAST is wonderfully special, in that it can be used to replace both OP_GV and OP_PADAV. The latter is only a baseop, whereas OP_AELEMFAST is a flagged as a padop/svop. baseops are smaller, and (therefore) don't have memory allocated where op_sv "should" be. --- diff --git a/CHANGES b/CHANGES index c9eae16..f07437e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ Revision history for Perl extension Devel::Size. +0.74_52 2011-04-23 nicholas + * Fix potential SEGVs for OP_AELEMFAST on a lexical (eg $foo[3]) + 0.74_51 2011-04-22 nicholas * Don't count PL_sv_{undef,no,yes} in the size returned * total_size() was double-counting entries in typeglobs diff --git a/Size.xs b/Size.xs index 654ff39..2a210e3 100644 --- a/Size.xs +++ b/Size.xs @@ -408,7 +408,11 @@ op_size(pTHX_ const OP * const baseop, struct state *st) TAG;break; case OPc_SVOP: TAG; st->total_size += sizeof(struct pmop); - sv_size(aTHX_ st, cSVOPx(baseop)->op_sv, TRUE); + if (!(baseop->op_type == OP_AELEMFAST + && baseop->op_flags & OPf_SPECIAL)) { + /* not an OP_PADAV replacement */ + sv_size(aTHX_ st, cSVOPx(baseop)->op_sv, TRUE); + } TAG;break; case OPc_PADOP: TAG; st->total_size += sizeof(struct padop); diff --git a/t/code.t b/t/code.t index 65aca0e..ab5d514 100644 --- a/t/code.t +++ b/t/code.t @@ -1,7 +1,7 @@ #!/usr/bin/perl -w use strict; -use Test::More tests => 8; +use Test::More tests => 10; use Devel::Size ':all'; sub zwapp; @@ -29,3 +29,14 @@ cmp_ok($anon_size, '>', 0, 'anonymous subroutines have a size'); cmp_ok(length prototype $anon_proto, '>', 0, 'prototype has a length'); cmp_ok($anon_proto_size, '>', $anon_size + length prototype $anon_proto, 'prototypes add to the size'); + +{ + use vars '@b'; + my $aelemfast_lex = total_size(sub {my @a; $a[0]}); + my $aelemfast = total_size(sub {my @a; $b[0]}); + + cmp_ok($aelemfast_lex, '>', $anon_size, + 'aelemfast for a lexical is handled correctly'); + cmp_ok($aelemfast, '>', $aelemfast_lex, + 'aelemfast for a package variable is larger'); +}