April 2017 Archives

Trials and troubles with changing @INC

With the upcoming 5.26 release series of Perl, there's a breaking change that's part of the release. The current directory, '.', is being removed from @INC. It's a good thing, it deals with a bunch of potential security problems and has been discussed more thoroughly elsewhere http://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243763.html and http://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243722.html

This means that a number of common patterns in many perl scripts, particularly tests, no longer work the way that they did in the past.

use inc::Module::Install;  # To get the bundled copy of Module::Install with a CPAN dist

# Usually used to setup some common test environment
#  or common functions for the tests
require 't/common_thing.pl';
use t::common;

# I'm not sure what the actual common use of this is, but it's also impacted.
do 'config.pl';

All of the above are going to fail to locate the files that you'd previously expect. Instead you'll get an error like this:

Configuring HTML-Tree-5.03 ... Can't locate inc/My_Build.pm in @INC 
  (you may need to install the inc::My_Build module) (@INC contains: 
    /home/ryan/perl5/perlbrew/perls/perl-blead/lib/site_perl/5.26.0/x86_64-linux 
    /home/ryan/perl5/perlbrew/perls/perl-blead/lib/site_perl/5.26.0 
    /home/ryan/perl5/perlbrew/perls/perl-blead/lib/5.26.0/x86_64-linux 
    /home/ryan/perl5/perlbrew/perls/perl-blead/lib/5.26.0) at Build.PL line 4.

There's a few things you can do to work around or fix your modules for this change.

# Quickly add '.' back into @INC, 
# not what I'd recommend as it just brings back the
# same potential security issues that need to be fixed
# but it will fix most issues almost immediately
use lib '.';

# explicitly say you want it from ./, This will also help prevent it
# from trying to load an appropriately named file in @INC that you didn't expect    
require './t/common_thing.pl'; 
do './config.pl';

With this big of a change, nobody really knew exactly what the impact would be on either users or CPAN, so a stop-gap measure was put in place. New versions of CPAN and CPANMinus now set the environment variable PERL_USE_UNSAFE_INC to tell perl to put '.' back into @INC when they're building, testing and installing modules. This works well enough but does mean that a badly written dist can still be subject to the potential problems that having '.' in @INC. You can prevent this, by explicitly setting the environment variable yourself to 0 but many modules will then fail to build or test properly.

Watching the p5p mailing list I saw some chatter about this that seemed that nobody had a complete picture of just how much of CPAN was actually impacted by this. There were a few users using the normal CPAN smoking tools to try to figure this out, but those tools won't find problems in some cases, i.e. something depends on something that's also broken. So I built a custom smoker to run through everything referenced on cpan in the index or as a dependency of another dist, and test them with '.' both in and out of @INC to see if they'd fail and then be able to continue on to anything that depended on them regardless of if they passed or failed.

It's taken a few weeks but it's finally finished running through every module it can. It's identified 2996 dists on CPAN that don't build with '.' removed from @INC. You can get a complete list of those failures, and the build logs, at http://cpan.simcop2387.info/failed.html

Of the failures, 2096 appear to be caused by/related to Module::Install and not being able to find inc::Module::Install during some phase of cpanm installing the module. I've also produced a report for every author at http://cpan.simcop2387.info/by_author/ There's also a list of all authors with failing modules, and how many they have at http://cpan.simcop2387.info/authors.txt.

There's also a gigantic 10MB page of every test result, http://cpan.simcop2387.info/test.html but be careful it'll make your browser hate you.

In the next few days I plan to rerun every failure to look for fixed modules and to clean up some of the general failures (those that failed regardless of @INC) by fixing up the most depended on modules and others that are easy to deal with. There are a few that I know failed during some periods where my internet went down and so those will get cleared up by rerunning them.

The code I used to produce all this can be found at https://gitea.simcop2387.info/simcop2387/treedeps. There's two storable files also in the repo that contain data about the tests: modcache.stor has the entire dependency tree for cpan (excluding loops), everything.stor has the high level test results and the order of how everything was tested.

About Ryan Voots

user-pic I blog about Perl. And never fill out bios.