Perl provides three logical operators: &&
, ||
, and !
, and they have the same meaning as in C.
Wiki Markup |
---|
Perl also provides three alternative logical operators: {{and}}, {{or}}, and {{not}}. They have the same meanings as {{&&}}, {{||}}, and {{\!}}. They have much lower binding precedence, which makes them useful for control flow \[[Wall 2011|AA. Bibliography#Manpages]\]. They are called the late-precedence logical operators, whereas {{&&}}, {{||}}, and {{!}} are called the early-precedence logical operators. |
It is possible to mix the early-precedence logical operators with the late-precedence logical operators, but this mixture of precedence often leads to confusing, counterintuitive behavior. Therefore, every Perl expression should use either the early-precedence operators or the late-precedence ones, never both.
Wiki Markup |
---|
\[[Conway 2005|AA. Bibliography#Conway 2005]\] recommends avoiding the use of {{not}} and {{and}} entirely and using {{or}} only in control-flow operations, as a failure mode: |
Code Block | ||
---|---|---|
| ||
print $filehandle $data or croak("Can't write to file: $!"); |
Noncompliant Code Example
This noncompliant code example checks a file for suitability as an output file. It does this by checking to see that the file does not exist.
Code Block | ||
---|---|---|
| ||
if (not -f $file) { |
This code is perfectly fine. However, it is later amended to also work if the file does exist but can be overwritten.
Code Block | ||||
---|---|---|---|---|
| ||||
if (not -f $file || -w $file) { |
This code will not behave as expected because the binding rules are lower for the not
operator than for the !
operator. Instead, this code behaves as follows:
Code Block | ||
---|---|---|
| ||
if (not (-f $file || -w $file)) { |
when the maintainer really wanted:
Code Block | ||
---|---|---|
| ||
if ((not -f $file) || -w $file) { |
Compliant Solution
This compliant solution uses the !
operator in conjunction with the ||
operator. This code has the desired behavior of determining if a file either does not exist or does exist but is overwritable.
Code Block | ||||
---|---|---|---|---|
| ||||
if (! -f $file || -w $file) { |
Compliant Solution
This compliant solution uses the early-precedence operators consistently. Again, the code works as expected.
Code Block | ||||
---|---|---|---|---|
| ||||
if (not -f $file or -w $file) { |
Risk Assessment
Mixing early-precedence operators with late-precedence operators can produce code with unexpected behavior.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP04-PL | low | unlikely | low | P1 | L3 |
Automated Detection
Tool | Diagnostic |
---|---|
Perl::Critic | ValuesAndExpressions::ProhibitMixedBooleanOperators |
Bibliography
Wiki Markup |
---|
\[[CPAN|AA. Bibliography#CPAN]\] [Elliot Shank, Perl-Critic-1.116|http://search.cpan.org/~elliotjs/Perl-Critic-1.116/] [ProhibitMixedBooleanOperators|http://search.cpan.org/~elliotjs/Perl-Critic-1.112_001/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMixedBooleanOperators.pm] \[[Conway 2005|AA. Bibliography#Conway 2005]\] pg. 70 \[[Wall 2011|AA. Bibliography#Manpages]\] [perlop|http://perldoc.perl.org/perlop.html] |