Home / Alt manpages / perl5260delta(1)

  • perl5260delta(1)
  • User command
  • linux

Perl 5.26 Compatibility Checks for Safer Module Loading

Use this checklist to find the Perl 5.26 changes most likely to affect an older script: the current directory is no longer in @INC, literal left braces in regular expressions need care, and a few old interfaces have gone. You will also test the new indented here-document syntax. Allow about 15 minutes for the checks, plus however long your own test suite takes.

Before you start

You need a shell, Perl and a copy of the script or module you intend to assess. The examples below only inspect or compile code. Run them as an ordinary user. Do not set PERL_USE_UNSAFE_INC in a system-wide profile: it restores a less safe module search path and can make code from an untrusted working directory executable.

The local perl5260delta(1) page describes the change from Perl 5.24.0 to 5.26.0. This machine currently reports Perl v5.38.2, so the checks show behaviour that remains present in a newer interpreter, not a way to install Perl 5.26.

$ perl -v
This is perl 5, version 38, subversion 2

1. Check the module search path

Perl 5.26 stopped adding the current directory, written as ., to @INC by default. A script that used require "Local.pm" or use Local without installing that module can therefore fail after an interpreter upgrade. The change closes a real risk: starting a script in an untrusted directory must not silently load Perl code from that directory.

$ perl -e 'print join("\n", @INC), "\n"'
$ perl -e 'print((grep { $_ eq "." } @INC) ? "dot present\n" : "dot absent\n")'
dot absent

Fix the script by giving its private library directory an explicit path. The -I option is suitable for a controlled invocation:

$ perl -I/path/to/project/lib bin/report.pl

For code that controls its own startup, an explicit library path is clearer still:

use FindBin qw($Bin);
use lib "$Bin/../lib";
use Local::Report;

Re-run the script's tests from a directory that is not the project root. If they only pass when launched from one particular directory, you have found a path assumption rather than fixed the problem.

Checkpoint: module loading

  • @INC does not contain . during normal execution.
  • Project modules are found through an explicit -I, use lib or installation path.
  • Tests pass when launched from a different working directory.

2. Use the temporary compatibility switch only to diagnose

If an old build still depends on the former search path, Perl provides PERL_USE_UNSAFE_INC=1. It appends . when the interpreter starts, except under taint mode. Use it for a one-command comparison while you locate the missing explicit path:

$ PERL_USE_UNSAFE_INC=1 perl -e 'print((grep { $_ eq "." } @INC) ? "dot present\n" : "dot absent\n")'
dot present

This is a compatibility crutch, not the repair. Remove it after the test. If you inherited it from a shell profile, packaging script or service unit, record why, replace the implicit lookup with an explicit path, and then remove the setting. Never use it to make a service load modules from a writable working directory.

3. Find literal braces in regular expressions

In Perl 5.26, a literal left brace in a regular expression pattern is generally required to be escaped. The unescaped form can become a fatal compilation error, although a few unambiguous positions were retained for compatibility. Search first, then make the intent explicit everywhere it is literal.

# Literal brace: escape it.
my $open = qr/\{/;

# A character class is another explicit literal form.
my $either = qr/[{}]/;

Compile the affected files without running them. The -c option checks syntax and exits after compilation:

$ perl -c path/to/script.pl
path/to/script.pl syntax OK

Do not mechanically add a backslash to every brace in a complex pattern without reviewing the expression. Braces used for quantifiers, such as {2,4}, are operators and must remain operators. The safe rule is to escape a brace only when the pattern means the brace character itself, then run tests that exercise the match.

4. Replace removed interfaces

The 5.26 changes include the removal of POSIX::tmpnam(). It was already deprecated and is unsafe as a temporary-name generator. Use File::Temp instead, because it can create a temporary file without leaving a name-only race between choosing a path and opening it.

use File::Temp qw(tempfile);

my ($fh, $path) = tempfile();
print {$fh} "report\n";
close $fh or die "close $path: $!";

Search your code and dependencies for removed calls, then compile the relevant test suite on the target interpreter:

$ rg -n 'POSIX::tmpnam|require ::' lib bin t
$ prove -l t

The bareword form require ::Foo::Bar is also no longer valid. Use a normal module name, such as require Foo::Bar, and let Perl resolve it through the intended module path.

5. Adopt the useful new syntax carefully

Perl 5.26 adds indented here-documents with the <<~ modifier. The closing delimiter may be indented, and Perl removes the matching leading whitespace from each content line. This makes generated or embedded text easier to read without adding those indentation spaces to the value.

if (1) {
    print <<~EOF;
      Hello there
      EOF
}

The output is:

Hello there

Lines that do not have the required leading whitespace are an error, so keep the content and delimiter aligned. This syntax is an optional improvement, not a compatibility fix: do not introduce it into a script that must still run on Perl versions before 5.26.

Other additions include /xx for more readable regular expressions and the dynamic capture arrays @{^CAPTURE}, %{^CAPTURE} and %{^CAPTURE_ALL}. Use them only after confirming the minimum Perl version for every deployment target.

Done means

  • Your script does not rely on . appearing in @INC.
  • PERL_USE_UNSAFE_INC is absent from normal user and service environments.
  • Literal regular-expression braces are explicit, while quantifier braces still work.
  • Temporary files use File::Temp, and removed module interfaces are gone.
  • The tests and syntax checks pass on the oldest Perl version you support.