-
Notifications
You must be signed in to change notification settings - Fork 76
Expand file tree
/
Copy pathInappropriateBitwiseOrShiftOperands.ql
More file actions
125 lines (120 loc) · 4.77 KB
/
InappropriateBitwiseOrShiftOperands.ql
File metadata and controls
125 lines (120 loc) · 4.77 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* @id cpp/misra/inappropriate-bitwise-or-shift-operands
* @name RULE-7-0-4: The operands of bitwise operators and shift operators shall be appropriate
* @description Bitwise and shift operators should only be applied to operands of appropriate types
* and values to avoid implementation-defined or undefined behavior.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-7-0-4
* scope/single-translation-unit
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/
import cpp
import codingstandards.cpp.misra
import codingstandards.cpp.misra.BuiltInTypeRules
import codingstandards.cpp.BinaryOperations
predicate isConstantExpression(Expr e) {
e instanceof Literal or
e.isConstant()
}
bindingset[right, leftType]
pragma[inline_late]
predicate isValidShiftConstantRange(Expr right, MisraCpp23BuiltInTypes::NumericType leftType) {
exists(int value |
value = right.getValue().toInt() and
value >= 0 and
value < leftType.getBuiltInSize() * 8
)
}
predicate isSignedConstantLeftShiftException(LShiftExpr shift) {
exists(
Expr left, Expr right, MisraCpp23BuiltInTypes::NumericType leftType, QlBuiltins::BigInt leftVal,
int rightVal, int maxBit
|
left = shift.getLeftOperand() and
right = shift.getRightOperand() and
leftType = left.getType() and
isConstantExpression(left) and
isConstantExpression(right) and
MisraCpp23BuiltInTypes::isSignedType(leftType) and
isValidShiftConstantRange(right, leftType) and
leftVal = left.getValue().toBigInt() and
rightVal = right.getValue().toInt() and
leftVal >= 0.toBigInt() and
maxBit = leftType.getBuiltInSize() * 8 - 1 and
// Check that no set bit is shifted into or beyond the sign bit
leftVal * 2.toBigInt().pow(rightVal) < 2.toBigInt().pow(maxBit)
)
}
from Expr x, string message
where
not isExcluded(x, ConversionsPackage::inappropriateBitwiseOrShiftOperandsQuery()) and
(
// Binary bitwise operators (excluding shift operations) - both operands must be unsigned
exists(BinaryBitwiseOpOrAssignOp op, Type operandType |
not op instanceof BinaryShiftOpOrAssignOp
|
x = op.getLeftOperand() and
operandType = op.getLeftOperand().getExplicitlyConverted().getType() and
not MisraCpp23BuiltInTypes::isUnsignedType(operandType) and
message =
"Bitwise operator '" + op.getOperator() +
"' requires unsigned numeric operands, but the left operand has type '" + operandType +
"'."
or
x = op.getRightOperand() and
operandType = op.getRightOperand().getExplicitlyConverted().getType() and
not MisraCpp23BuiltInTypes::isUnsignedType(operandType) and
message =
"Bitwise operator '" + op.getOperator() +
"' requires unsigned numeric operands, but the right operand has type '" + operandType +
"'."
)
or
// Bit complement operator - operand must be unsigned
exists(ComplementExpr comp, Type opType |
x = comp.getOperand() and
opType = comp.getOperand().getExplicitlyConverted().getType() and
not MisraCpp23BuiltInTypes::isUnsignedType(opType) and
message =
"Bit complement operator '~' requires unsigned operand, but has type '" + opType + "'."
)
or
// Shift operators - left operand must be unsigned
exists(BinaryShiftOpOrAssignOp shift, Type leftType |
x = shift.getLeftOperand() and
leftType = shift.getLeftOperand().getExplicitlyConverted().getType() and
not MisraCpp23BuiltInTypes::isUnsignedType(leftType) and
not isSignedConstantLeftShiftException(shift) and
message =
"Shift operator '" + shift.getOperator() +
"' requires unsigned left operand, but has type '" + leftType + "'."
)
or
// Shift operators - right operand must be unsigned or constant in valid range
exists(
BinaryShiftOpOrAssignOp shift, Expr right, Type rightType,
MisraCpp23BuiltInTypes::NumericType leftType
|
right = shift.getRightOperand() and
x = right and
rightType = right.getExplicitlyConverted().getType() and
leftType = shift.getLeftOperand().getExplicitlyConverted().getType()
|
if exists(right.getValue().toInt())
then
not isValidShiftConstantRange(right, leftType) and
message =
"Shift operator '" + shift.getOperator() + "' shifts by " + right.getValue().toInt() +
" which is not within the valid range 0.." + ((leftType.getBuiltInSize() * 8) - 1) + "."
else (
not MisraCpp23BuiltInTypes::isUnsignedType(rightType) and
message =
"Shift operator '" + shift.getOperator() +
"' requires unsigned right operand, but has type '" + rightType + "'."
)
)
)
select x, message