-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathPossibleLossOfPrecision.ql
More file actions
92 lines (80 loc) · 2.63 KB
/
PossibleLossOfPrecision.ql
File metadata and controls
92 lines (80 loc) · 2.63 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
81
82
83
84
85
86
87
88
89
90
91
92
/**
* @name Possible loss of precision
* @description Dividing or multiplying integral expressions and converting the result to a
* floating-point value may result in a loss of precision.
* @kind problem
* @problem.severity error
* @precision high
* @id cs/loss-of-precision
* @tags reliability
* correctness
* external/cwe/cwe-190
* external/cwe/cwe-192
* external/cwe/cwe-197
* external/cwe/cwe-681
*/
import csharp
/** Holds if `e` is converted to type `t` which is a `float` or a `decimal`. */
predicate convertedToFloatOrDecimal(Expr e, Type t) {
exists(CastExpr cast |
cast.getExpr() = e and
t = cast.getType()
|
t instanceof FloatingPointType or
t instanceof DecimalType
)
or
exists(BinaryArithmeticOperation op |
op.getAnOperand() = e and
convertedToFloatOrDecimal(op, t)
|
op instanceof AddExpr or
op instanceof SubExpr or
op instanceof MulExpr
)
}
/** Holds if `div` is an exact integer division. */
predicate exactDivision(DivExpr div) {
exists(int numerator, int denominator |
numerator = div.getNumerator().stripCasts().getValue().toInt() and
denominator = div.getDenominator().stripCasts().getValue().toInt() and
numerator % denominator = 0
)
}
/** An expression that may result in a loss of precision. */
abstract class LossOfPrecision extends Expr {
Type convertedType;
LossOfPrecision() {
getType() instanceof IntegralType and
convertedToFloatOrDecimal(this, convertedType)
}
/** Gets the alert message. */
abstract string getMessage();
}
/** A division expression that may result in a loss of precision. */
class DivLossOfPrecision extends LossOfPrecision, DivExpr {
DivLossOfPrecision() { not exactDivision(this) }
override string getMessage() { result = "Possible loss of precision: any fraction will be lost." }
}
/** Holds if `e` is a constant multiplication that does not overflow. */
predicate small(MulExpr e) {
exists(float lhs, float rhs, float res, IntegralType t |
lhs = e.getLeftOperand().stripCasts().getValue().toFloat() and
rhs = e.getRightOperand().stripCasts().getValue().toFloat() and
lhs * rhs = res and
t = e.getType() and
not res < t.minValue() and
not res > t.maxValue()
)
}
/** A multiplication expression that may result in a loss of precision. */
class MulLossOfPrecision extends LossOfPrecision, MulExpr {
MulLossOfPrecision() { not small(this) }
override string getMessage() {
result =
"Possible overflow: result of integer multiplication cast to " +
convertedType.toStringWithTypes() + "."
}
}
from LossOfPrecision e
select e, e.getMessage()