develooper Front page | perl.perl5.porters | Postings from May 2013

[perl #117941] CopSTASH is not reference counted, and hence can become corrupt

From:
Nicholas Clark
Date:
May 10, 2013 11:36
Subject:
[perl #117941] CopSTASH is not reference counted, and hence can become corrupt
Message ID:
rt-3.6.HEAD-6955-1368185771-462.117941-75-0@perl.org
# New Ticket Created by  Nicholas Clark 
# Please include the string:  [perl #117941]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=117941 >


$ ~/Sandpit/5000/bin/perl -e 'sub B {package A; reset}; delete $::{"A::"}; B()'
Segmentation fault: 11 (core dumped)
$ ~/Sandpit/5000/bin/perl -v

This is perl, version 5.000


Copyright 1987-1994, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5.0 source kit.

Still present in blead (obviously, else I would not have reported it)

The bug isn't in reset - that's just the easiest way I found to write code
which accesses CopSTASH()


The slightly less contrived code:

$ perl -e 'package A; sub B {reset}; package main; $a = \&A::B; delete $::{"A::"}; $a->()'


only started failing after this commit:

commit e15faf7d09c73a41f95fbe6a0045ad5b17c899a6
Author: Nicholas Clark <nick@ccl4.org>
Date:   Thu Jun 23 21:30:33 2005 +0000

    Remove the reference loop between symbol tables and typeglobs.
    Typeglobs now have a weak reference onto their symbol table.
    
    p4raw-id: //depot/perl@24966


Before then there was no corruption, because that loop caused the structures
to leak and hence never be freed.


The correct solution is not immediately obvious, as just "bumping" the
reference count when creating the COP would create a lot of loops
(stash -> GV -> CV -> stash).

It might be appropriate to optimise the usual case of the COP's package being
the same as the package of the PVCV, and indirecting via the PVCV in that
case (as CvSTASH is already correctly implemented as a weak reference),
and hold a proper reference if CopSTASH is not the same as
CvSTASH(PL_compiling). In that case, loops, if they exist, will leak.

Whilst that will work for the default build, it's not clear to me how how to
make this work efficiently under ithreads, as the OP isn't allowed to
directly hold a pointer to the CV. (In a cloned child thread, the cloned
CV will be at a different address, but the OP is shared)

Nicholas Clark




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About