Audit Perl Scripts with the perltrap Checklist
You will use perltrap(1) as a focused review checklist for Perl scripts, then run small checks that expose the most common assumptions. The page is documentation, not a command that rewrites your code. On this machine it comes from perl-doc version 5.38.2-3.2ubuntu0.6 and describes Perl v5.38.2. Allow about fifteen minutes for a short script, or longer if it reads input and mixes several programming languages.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Confirm the installed guide
- 2. Put warnings and strict mode at the top
- 3. Check which value is being compared
- 4. Inspect input loops and the default variable
- 5. Review operators that look familiar
- 6. Check arrays, hashes and scopes
- 7. Recheck shell and language assumptions
- 8. Finish with a repeatable review
You need a shell and Perl. The examples are ordinary, unprivileged commands. They print values or diagnostics and do not alter files, services or interpreter settings.
1. Confirm the installed guide
Read the local manual before applying advice from a different Perl release. The manual is the authoritative reference for this installed package, and its first warning is practical: enable warnings, use strict code, and read the changes for the Perl version you are running.
$ command -v perl
/usr/bin/perl
$ perl -v | sed -n '1,4p'
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-gnu-thread-multi
$ man perltrap
Checkpoint: if man perltrap is unavailable, install the documentation package through your normal system administration process. Do not copy examples from memory while the local manual is missing.
2. Put warnings and strict mode at the top
Start a script with lexical warnings and strict checks. They catch different classes of mistakes: warnings report suspicious behaviour, while strict mode rejects several ambiguous or unsafe constructs during compilation.
use strict;
use warnings;
my $name = 'Ada';
print "hello $name\n";
Check a file without running it by using Perl's compile-only switch:
$ perl -c example.pl
example.pl syntax OK
This is a read-only check of the source. It still parses the whole program, so a failure can be reported before any normal runtime action. Fix the first diagnostic, then run the check again.
3. Check which value is being compared
Perl uses different operators for strings and numbers. Use eq, ne and their string-ordering relatives for text. Use ==, != and numeric ordering for numbers. A shell or another language may have taught you a different set of operators.
use strict;
use warnings;
my $answer = '10';
print "text match\n" if $answer eq '10';
print "numeric match\n" if $answer == 10;
$ perl comparison.pl
text match
numeric match
Checkpoint: for every comparison in a ported script, ask whether both operands are text, both are numbers, or one is being converted. Do not change an operator merely to silence a warning. Decide what the input means first.
4. Inspect input loops and the default variable
A Perl program runs once unless you create a loop. The -n and -p switches provide implicit input loops for command-line filters, but an ordinary script needs an explicit loop. The manual also warns that a line read is normally in $_, and normally retains its newline.
$ printf 'red\nblue\n' | perl -ne 'chomp; print "$_\n"'
red
blue
In a file, make the assignment and newline handling visible:
use strict;
use warnings;
while (my $line = <STDIN>) {
chomp $line;
print "$line\n";
}
This avoids a common distraction: <FH> is a readline operation, not the name of a filehandle. A bare read outside a useful condition can discard the value. Also remember that the current input line is not automatically split into fields. Split it explicitly when that is what the program requires.
5. Review operators that look familiar
Several traps in perltrap are visual lookalikes. Matching uses =~, not assignment with =. Exponentiation uses **, while ^ is bitwise XOR. Concatenation uses a dot, not an empty string. C and C++ developers should use elsif, last and next for the corresponding control-flow jobs.
$ perl -e 'my $x = "perl"; print "matched\n" if $x =~ /erl/; print 2 ** 3, "\n"; print "a" . "b", "\n"'
matched
8
ab
Keep parentheses around unfamiliar expressions while reviewing them. Perl builtins can have unary or list-operator behaviour, and context can change the result of an operation. A line that looks plausible is not proof that it receives the context you intended.
6. Check arrays, hashes and scopes
The checklist calls out zero-based indexes, the difference between numeric and string keys, and the fact that merely referring to a hash value does not create it. It also distinguishes my from local: my creates a lexical variable, while local temporarily changes a global value and can produce dynamic-scope side effects.
use strict;
use warnings;
my @colours = ('red', 'blue');
my %count = (red => 2);
print "$colours[0]\n";
print "$count{red}\n";
print "missing\n" unless exists $count{green};
When iterating a hash, say whether you want keys or values. The safe, readable form is for my $key (keys %hash). Writing a hash in a list context and assuming it yields key-value pairs can silently produce an alternating sequence instead.
7. Recheck shell and language assumptions
Shell syntax is not Perl syntax. Script arguments are in @ARGV, not $1 and $2. String tests use eq and ne, while numeric tests use == and !=. Perl also compiles the complete program before running it, apart from BEGIN blocks, so a late syntax error prevents normal execution.
$ perl -e 'print "first argument: $ARGV[0]\n"' example-value
first argument: example-value
Do not assume that backticks behave like the shell that launched the script. The manual documents interpolation and return-value differences. If a script constructs a command from external input, stop for a separate security review before changing it. Testing syntax is not the same as making command execution safe.
8. Finish with a repeatable review
Run the local guide again after fixing the obvious traps, then compile the complete script and test it with representative input. Keep the original input and output paths unchanged during this review. No elevated privileges are needed for any command shown here.
$ man perltrap
$ perl -c example.pl
example.pl syntax OK
$ printf 'one\ntwo\n' | perl example.pl
one
two
If the script reads files, add a harmless test fixture rather than pointing the first run at production data. If it writes files, use a temporary directory and check the output before replacing anything. The guide identifies traps; it cannot prove that application logic, permissions or external commands are correct.
Done means
perltrap(1)was read from the installedperl-docpackage.- The script starts with
use strictanduse warnings, where compatible with its design. - String, numeric and matching operators were checked deliberately.
- Input loops,
$_,@ARGV, context, indexes and scopes were reviewed. perl -creports syntax OK before the representative test run.