Skip Menu |

This queue is for tickets about the version CPAN distribution.

Report information
The Basics
Id: 47980
Status: resolved
Priority: 0/
Queue: version

People
Owner: Nobody in particular
Requestors: adamk [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: (no value)
Fixed in: (no value)



Subject: Major bug in Module::Build::Version 0.77
There is a very nasty bug in Module::Build::Version 0.77. The _VERSION hook (implementing a UNIVERSAL::VERSION wrapper?) seems to implement a run-time class autoloader. What's worse, this autoloader is completely unsafe about checking the result of the require call. If for some reason an eval is done in a parent scope of the ->VERSION method, putting a value into $@, then this value seems to be checked and matches the check for Module::Build::Version's own require eval response. The result is that, if an require eval fails, every single ->VERSION call from that scope downwards return undef. version::vpp::_VERSION((eval 273)[C:\strawberry\perl\lib/Module/Build/Version.pm :31]:516): 516: eval "require $class" unless %{"$class\::"}; # already existing DB<8> s version::vpp::_VERSION((eval 273)[C:\strawberry\perl\lib/Module/Build/Version.pm :31]:517): 517: return undef if $@ =~ /Can't locate/ and not defined $req; DB<8> x $@ 0 "Can't locate Class/Autouse.pm in \@INC (\@INC contains: C:\\strawberry\\cpan \\build\\Padre-0.40-hYgCQP\\blib\\arch C:\\strawberry\\cpan\\build\\Padre-0.40-h YgCQP\\blib\\lib C:/strawberry/perl/lib C:/strawberry/perl/site/lib .) at (eval 71)[t\\11-badcode.t:25] line 1.\cJ at (eval 71)[t\\11-badcode.t:25] line 1\cJ\cI main::BEGIN() called at Class/Autouse.pm line 1\cJ\cIeval {...} called at Class/ Autouse.pm line 1\cJ\cIeval 'use Class::Autouse \\':devel\\';' called at t\\11-b adcode.t line 25\cJBEGIN failed--compilation aborted at (eval 71)[t\\11-badcode. t:25] line 1.\cJ at (eval 71)[t\\11-badcode.t:25] line 1\cJ\cIeval 'use Class::A utouse \\':devel\\';' called at t\\11-badcode.t line 25\cJ" DB<9> x version->VERSION 0 undef DB<10> x $version::VERSION 0 0.77 DB<11>
Key line appears to be: eval "require $class" unless %{"$class\::"}; $@ needs to be cleared before this line, in case the eval is skipped, otherwise, preexisting global $@ can trigger subsequent code. This line appears to go back at least to 0.74.
On Fri Jul 17 12:41:42 2009, DAGOLDEN wrote: Show quoted text
> Key line appears to be: > > eval "require $class" unless %{"$class\::"};
Just don't check $@ unless we have done the eval. === lib/Module/Build/Version.pm ================================================================== --- lib/Module/Build/Version.pm (revision 2640) +++ lib/Module/Build/Version.pm (local) @@ -628,15 +628,17 @@ my $class = ref($obj) || $obj; no strict 'refs'; - eval "require $class" unless %{"$class\::"}; # already existing - return undef if $@ =~ /Can't locate/ and not defined $req; + unless %{"$class\::"} { # class not already loaded + eval "require $class"; + return undef if $@ =~ /Can't locate/ and not defined $req; + } if ( not %{"$class\::"} and $] >= 5.008) { # file but no package require Carp; Carp::croak( "$class defines neither package nor VERSION" ."--version check failed"); } - + my $version = eval "\$$class\::VERSION"; if ( defined $version ) { local $^W if $] <= 5.008;
Resolved in a much smarter way for 0.77; we don't need to dynamically load the class at all. The only time we need to go down this code path is if: A module has been loaded and 1) 'package' was not used and 2O there was no $VERSION assignment at all In this case, the "module" will exist as %INC{'module.pm'} but there will not be a stash %{'module::'}. John