Perl provides two sets of comparison operators; one set for working with numbers, and one set for working with strings.
Numbers |
Strings |
---|---|
== |
eq |
!= |
ne |
< |
lt |
<= |
le |
> |
gt |
>= |
ge |
<=> |
cmp |
Do not use the number comparison operators on non-numeric strings. Likewise, do not use the string comparison operators on numbers.
Noncompliant Code Example (numbers)
This noncompliant code example improperly uses eq
to test two numbers for equality. Counterintuitively, this code prints false.
my $num = 02; # ... if ($num eq "02") {print "true\n"} else {print "false\n"};
The counterintuitive result arises from the fact that $num
is interpreted as a number. When it is initialized, the 02
string is converted to its numeric representation, which is 2
. When it is compared, it is convered back to a string, but this time it has the value 2
, and so the string comparison fails.
Compliant Solution (numbers)
This compliant colution uses ==
which interprets its arguments as numbers. Thus this code prints true
, even though the right argument to ==
is explicitly provided as a string.
my $num = 02; # ... if ($num == "02") {print "true\n"} else {print "false\n"};
Noncompliant Code Example (strings)
This noncompliant code example improperly uses ==
to test two strings for equality.
sub check_password { my $correct = shift; my $password = shift; # encrypt password if ($password == $correct) { return true; } else { return false; } }
The ==
operator first converts its arguments into numbers. This is done by extracting digits from the front of each arguments (along with a preceding +
or -
). Non-numeric data in an argument is ignored, and the number consists of whatever digits were extract. A string such as "goodpass
" has no leading digits, and is thus converted to the numeral 0. Consequently, unless either $password
or $correct
contains leading digits, they will both be converted to 0, and will therefore be considered equivalent.
Compliant Solution (strings)
This compliant colution uses eq
which interprets its arguments as strings.
sub check_password { my $correct = shift; my $password = shift; # encrypt password if ($password eq $correct) { return true; } else { return false; } }
Risk Assessment
Confusing the string comparison operators with numeric comparison operators can lead to incorrect program behavior or incorrect program data.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXP35-PL |
low |
likely |
low |
P9 |
L2 |
Automated Detection
Tool |
Diagnostic |
---|---|
Perl::Critic |
ValuesAndExpressions::ProhibitMismatchedOperators |
Bibliography
EXP11-C. Do not apply operators expecting one type to data of an incompatible type 03. Expressions (EXP) EXP13-C. Treat relational and equality operators as if they were nonassociative