Perl provides several mechanisms for warning the user about potential problems with the program. The use warnings
pragma turns on a default set of warnings for the Perl runtime to produce should it detect questionable code. The -w
command-line argument serves the same purpose. It is considered so useful that the perl(1)
manpage dryly notes the first bug in Perl is that "the -w
switch is not mandatory" [Wall 2011] .
The use warnings
pragma must be used in all Perl code.
One of the modules that Perl provides for additional safety is the strict
module. It identifies programming constructs that are likely to be errors, such as unqualified and undeclared variables (that might be typos), dangerous references, and unqualified subroutine names. The use strict
pragma must also be used in all Perl code.
However, occasionally there is a need to disable warnings or strictness for some code that may look strange but is actually correct. The -w
switch cannot enable or disable particular warnings on particular ranges of code. When a particular warning or strict checking must be disabled, the no warnings
or no strict
pragmas should be used in as minimal a scope as possible. They should also disable the specific warning or strictness checker that would trigger a warning or fatal error rather than disable all checks.
Noncompliant Code Example (warnings
)
This noncompliant code example contains code that produces an unchecked warning.
use warnings; use strict; my %days = ("Sunday" => 'pray', "Monday" => 'work', "Tuesday" => 'work', "Wednesday" => 'work', "Thursday" => 'work', "Friday" => 'work', "Saturday" => 'rest'); sub what_to_do { my $day = shift; if ($days{$day} eq 'work') { return 'work hard'; } if (exists $days{$day}) { return $days{$day}; } else { return "do nothing"; } } my $task = what_to_do('tomorrow'); print "Prepare to $task\n";
This code produces the following output:
Use of uninitialized value within %days in string eq at ./example.pl line 16. Prepare to do nothing
Noncompliant Code Example (warnings
)
This noncompliant code example attempts to suppress the particular warning printed.
use warnings; use strict; no warnings 'uninitialized'; my %days = ("Sunday" => 'pray', # ...
Unfortunately, although this code correctly suppresses the warning message, it has the undesired effect of suppressing the warning message throughout the entire program and will likely suppress the warning in other lines of code that are not known to be correct.
Compliant Solution (warnings
)
This compliant solution suppresses the warning in as minimal a scope as possible. Because the uninitialized
warning is suppressed only inside the what_to_do
subroutine, other regions of the code can still generate this warning.
sub what_to_do { my $day = shift; no warnings 'uninitialized'; if ($days{$day} eq 'work') { return 'work hard'; } if (exists $days{$day}) { return $days{$day}; } else { return "do nothing"; } }
Noncompliant Code Example (strict
)
This noncompliant code example contains code that references a nonexistant variable.
use strict; use warnings; our $sunday = 'pray'; our $monday = 'work'; our $tuesday = 'work'; our $wednesday = 'work'; our $thursday = 'work'; our $friday = 'work'; our $saturday = 'rest'; sub what_to_do { my $day = shift; no warnings 'uninitialized'; if ($$day eq 'work') { return 'work hard'; } if (defined $$day) { return $$day; } else { return "do nothing"; } } my $task = what_to_do('tomorrow'); print "Prepare to $task\n";
The strict
pragma catches the improper reference and aborts the program, producing the following error message:
Can't use string ("tomorrow") as a SCALAR ref while "strict refs" in use at ./example.pl line 19.
Noncompliant Code Example (strict
)
This noncompliant code example disables the strict
pragma, producing proper output. However, strictness is suppressed throughout the entire program.
use warnings; use strict; no strict 'refs'; our $sunday = 'pray'; # ...
This code produces the following output:
Prepare to do nothing
This example may be considered correct, but the code works by referencing a nonexistent variable $tomorrow
.
Compliant Solution (strict
)
This compliant solution suppresses the strictness checking to as minimal a scope as possible. Because the strictness checking is suppressed only inside the what_to_do
subroutine, other regions of the code can still be checked for strict compliance.
sub what_to_do { my $day = shift; no warnings 'uninitialized'; no strict 'refs'; if ($$day eq 'work') { return 'work hard'; } if (defined $$day) { return $$day; } else { return "do nothing"; } }
Risk Assessment
Suppressing warnings can mask problems that would otherwise be quickly recognized and fixed.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC02-PL | Low | Unlikely | Medium | P2 | L3 |
Automated Detection
Tool | Diagnostic |
---|---|
Perl::Critic | TestingAndDebugging::ProhibitNoStrict |
Perl::Critic | TestingAndDebugging:;ProhibitNoWarnings |
Perl::Critic | TestingAndDebugging::ProhibitProlongedStrictureOverride |
Perl::Critic | TestingAndDebugging::RequireUseStrict |
Related Guidelines
SEI CERT C Coding Standard | MSC00-C. Compile cleanly at high warning levels |
---|---|
SEI CERT C++ Coding Standard | VOID MSC00-CPP. Compile cleanly at high warning levels |
Bibliography
2 Comments
Anonymous
Note that running with warnings turned on in production has the potential to fill up a disk. Warnings and their priorities can change between versions of Perl, so things that did not warn before might warn after an upgrade.
Warnings are a developer tool and do nothing to prevent anything bad.
David Svoboda
I will agree that warnings do little direct good for users, since by definition they can't fix them. And clearly, if you have a long-running system that logs warnings, it is possible for said warnings to exhaust filesystem space.
On the other paw, however, warnings do lots of indirect good for users, by scaring them into questioning the quality of the code. As noted by this rule, Perl warnings can be suppressed on a localized basis. This makes it simple to ship warning-free code.
Therefore, I will assert that suppressed warnings pose a greater liability to a user than a filesystem full of warnings