-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathContainerSizeCmpZero.ql
More file actions
80 lines (73 loc) · 2.57 KB
/
ContainerSizeCmpZero.ql
File metadata and controls
80 lines (73 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* @name Container size compared to zero
* @description Comparing the size of a container to zero with this operator will always return the same value.
* @kind problem
* @problem.severity warning
* @precision very-high
* @id cs/test-for-negative-container-size
* @tags quality
* reliability
* correctness
*/
import csharp
import semmle.code.csharp.commons.Assertions
private predicate propertyOverrides(Property p, string qualifier, string baseClass, string property) {
exists(Property p2 |
p2.getUnboundDeclaration().getDeclaringType().hasFullyQualifiedName(qualifier, baseClass) and
p2.hasName(property)
|
p.overridesOrImplementsOrEquals(p2)
)
}
private predicate containerSizeAccess(PropertyAccess pa, string containerKind) {
(
propertyOverrides(pa.getTarget(), "System.Collections.Generic", "ICollection`1", "Count") or
propertyOverrides(pa.getTarget(), "System.Collections.Generic", "IReadOnlyCollection`1", "Count") or
propertyOverrides(pa.getTarget(), "System.Collections", "ICollection", "Count")
) and
containerKind = "a collection"
or
(
propertyOverrides(pa.getTarget(), "System", "String", "Length") and containerKind = "a string"
or
propertyOverrides(pa.getTarget(), "System", "Array", "Length") and containerKind = "an array"
)
}
class ZeroLiteral extends Expr {
ZeroLiteral() { this.getValue() = "0" }
}
/**
* Whether `smaller` is checked to be no greater than `greater` by `e` being `trueOrFalse`
*/
private predicate checkedLT(BinaryOperation e, Expr greater, Expr smaller, string trueOrFalse) {
greater = e.(GEExpr).getLeftOperand() and
smaller = e.(GEExpr).getRightOperand() and
trueOrFalse = "true"
or
greater = e.(LEExpr).getRightOperand() and
smaller = e.(LEExpr).getLeftOperand() and
trueOrFalse = "true"
or
greater = e.(GTExpr).getRightOperand() and
smaller = e.(GTExpr).getLeftOperand() and
trueOrFalse = "false"
or
greater = e.(LTExpr).getLeftOperand() and
smaller = e.(LTExpr).getRightOperand() and
trueOrFalse = "false"
}
private predicate comparisonOfContainerSizeToZero(
BinaryOperation e, string containerKind, string trueOrFalse
) {
exists(Expr sizeAccess |
containerSizeAccess(sizeAccess, containerKind) and
checkedLT(e, sizeAccess, any(ZeroLiteral zl), trueOrFalse)
)
}
from BinaryOperation e, string containerKind, string trueOrFalse
where
comparisonOfContainerSizeToZero(e, containerKind, trueOrFalse) and
not isExprInAssertion(e)
select e,
"This expression is always " + trueOrFalse + ", since " + containerKind +
" can never have negative size."