IndexOf result compared against a positive bound
ID |
vbnet.maintainability.indexof_check_wrong_bound |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Control Flow |
Language |
VB.NET |
Description
Reports the result of IndexOf or LastIndexOf being compared against a positive bound -
> 0, >= 1, < 1 or ⇐ 0 - where the "not found" sentinel is -1 and the correct
bound is therefore 0.
Rationale
IndexOf and LastIndexOf return the zero-based position of the item and -1 when it is
not present, so a match at the very first position returns 0. Testing > 0 or >= 1
therefore treats a match at position 0 exactly like "not found": path.IndexOf("/") > 0
reports False for "/etc/passwd", and list.IndexOf(item) > 0 reports False for the
first element. The negated forms < 1 and ⇐ 0 are wrong in the same way, reporting
"absent" for an item found at position 0. The result is an off-by-one that only shows up on
the boundary case, so it survives ordinary testing.
The following code illustrates the pattern detected by this rule:
Public Function HasSeparator(ByVal header As String) As Boolean
' FLAGGED: IndexOf result compared against a positive bound
Return header.IndexOf(":") > 0
End Function
Remediation
Compare against the sentinel, not against a positive number: use >= 0 (or <> -1) for
"found" and < 0 (or = -1) for "not found". When the position itself is not needed, prefer
the intent-revealing Contains for strings and collections, or StartsWith when the test is
really about the first position.
' Before: False for a separator at position 0
Return header.IndexOf(":") > 0
' After
Return header.IndexOf(":") >= 0
' Or, when the position is not needed
Return header.Contains(":")