develooper Front page | perl.perl5.porters | Postings from January 2005

Re: [perl #33927] [BUG] Coredump in 5.9.2 when evalling a certain string while in a coderf in @INC

Thread Previous | Thread Next
From:
Jos I. Boumans
Date:
January 25, 2005 12:10
Subject:
Re: [perl #33927] [BUG] Coredump in 5.9.2 when evalling a certain string while in a coderf in @INC
Message ID:
12CDCBC7-6F0D-11D9-8B37-000A956B0E06@xs4all.net

On Jan 25, 2005, at 7:54 PM, John Peacock wrote:

> kane@coke.xs4all.nl (via RT) wrote:
>>     package core;
>>     use strict;
>>     sub import {
>>         require lib;
>>         lib->import( sub { eval q[*UNIVERSAL::VERSION = $old_version] 
>> })
>>     }        1;
>
> Examining the code in Module::Build::Base, I can see why this would 
> coredump, since you stripped out all of the important bits.  
> Effectively you are nuking the &UNIVERSAL::VERSION subroutine.
I wasn't aware that method always existed, but good to know.

[...]
> If you tell me what you are actually attempting to do, I might be able 
> to suggest something different.

What happens in the code is this bit (where we are reading the source 
of a module):

	### XXX stolen from module::load::conditional ###
     while (local $_ = <$fh> ) {
    		### the following regexp comes from the
         ### ExtUtils::MakeMaker documentation.
         if ( /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/ ) {

             ### this will eval the version in to $VERSION if it
             ### was declared as $VERSION in the module.
             ### else the result will be in $res.
             ### this is a fix on skud's Module::InstalledVersion
             local $VERSION;
             my $res = eval $_;

             ### default to '0.0' if there REALLY is no version
             ### all to satisfy warnings
             $found = $VERSION || $res || '0.0';

             ### found what we came for
             last if $found;
         }
     }

Basically this tries to find the version of the module we're looking at.
As you can see from the comments, this technique is used in various 
modules,
including CPANPLUS::inc (which conditionally loads bundled modules, if 
their
version is higher than what's on the os, or the module is not on the os 
at all).

In Module::Build::Base we don't find a VERSION declaration anywhere, 
until there, so that's the string that gets evaled into a version. eval 
is sadly the only resort as many modules use some perl code to generate 
the version. Most notably is the parsing of RCS tags.

I suppose if Module::Build::Base would say, at the top:

	$VERSION = $Module::Build::VERSION

this would make EU::MM, M::IV, M::L::C and of course CPANPLUS::inc find 
a 'real' version declaration, rather than something evil that will blow 
away UNIVERSAL::VERSION.

But that doesn't stop anyone else from implementing a bit of code that 
will make perl segfault, so surely there's somethign we can also do 
from the perl world to make this DTRT.

As noted, perl 5.6.x and 5.8.x don't suffer from this problem.

> I disagreed with the way that M::B was changed as described in the 
> comment above, so it may be that this issue will have to be reopened 
> with the M::B folks.  If this is related to the laudable attempt to 
> move M::B into the core, the above code will have no effect 
> whatsoever, since the version.pm module is a stub in 5.9+; all of the 
> UNIVERSAL::VERSION changes are in the core already.
Actually, it's 5.9+ that's segfaulting, nothing else so far...

Thanks for your insights, they certainly pointed out where the problem 
lies :)

--

Jos Boumans

	"Whenever you find you are on the side of the majority,
	it is time to pause and reflect." - Mark Twain

	CPANPLUS	http://cpanplus.sf.net


Thread Previous | Thread Next


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