Skip to content

Commit 907e158

Browse files
committed
Finalize INT34-C
1 parent 3778724 commit 907e158

File tree

1 file changed

+45
-56
lines changed

1 file changed

+45
-56
lines changed

c/cert/src/rules/INT34-C/ExprShiftedbyNegativeOrGreaterPrecisionOperand.ql

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import cpp
1414
import codingstandards.c.cert
1515
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
16+
import semmle.code.cpp.ir.internal.ASTValueNumbering
1617
import semmle.code.cpp.controlflow.Guards
1718

1819
/*
@@ -34,6 +35,21 @@ class PrecisionMacro extends Macro {
3435
PrecisionMacro() { this.getName().toLowerCase().matches("precision") }
3536
}
3637

38+
class LiteralZero extends Literal {
39+
LiteralZero() { this.getValue() = "0" }
40+
}
41+
42+
class BitShiftExpr extends BinaryBitwiseOperation {
43+
BitShiftExpr() {
44+
this instanceof LShiftExpr or
45+
this instanceof RShiftExpr
46+
}
47+
48+
override string toString() {
49+
if this instanceof LShiftExpr then result = "left-shift" else result = "right-shift"
50+
}
51+
}
52+
3753
int getPrecision(BuiltInType type) {
3854
type.(CharType).isExplicitlyUnsigned() and result = type.(CharType).getSize() * 8
3955
or
@@ -66,80 +82,53 @@ int getPrecision(BuiltInType type) {
6682
result = type.(LongLongType).getSize() * 8 - 1
6783
}
6884

69-
predicate isForbiddenLShiftExpr(LShiftExpr binbitop, string message) {
85+
predicate isForbiddenShiftExpr(BitShiftExpr shift, string message) {
7086
(
7187
(
72-
getPrecision(binbitop.getLeftOperand().getUnderlyingType()) <=
73-
upperBound(binbitop.getRightOperand()) and
88+
getPrecision(shift.getLeftOperand().getUnderlyingType()) <=
89+
upperBound(shift.getRightOperand()) and
7490
message =
75-
"The operand " + binbitop.getLeftOperand() + " is left-shifted by an expression " +
76-
binbitop.getRightOperand() + " which is greater than or equal to in precision."
91+
"The operand " + shift.getLeftOperand() + " is " + shift + "ed by an expression " +
92+
shift.getRightOperand() + " which is greater than or equal to in precision."
7793
or
78-
lowerBound(binbitop.getRightOperand()) < 0 and
94+
lowerBound(shift.getRightOperand()) < 0 and
7995
message =
80-
"The operand " + binbitop.getLeftOperand() + " is left-shifted by a negative expression " +
81-
binbitop.getRightOperand() + "."
82-
)
83-
or
84-
/* Check a guard condition protecting the shift statement: heuristic (not an iff query) */
85-
exists(GuardCondition gc, BasicBlock block, Expr precisionCall |
86-
block = binbitop.getBasicBlock() and
87-
(
88-
precisionCall.(FunctionCall).getTarget() instanceof PopCount
89-
or
90-
precisionCall = any(PrecisionMacro pm).getAnInvocation().getExpr()
91-
)
92-
|
93-
/*
94-
* Shift statement is at a basic block where
95-
* `shift_rhs < PRECISION(...)` is ensured
96-
*/
97-
98-
not gc.ensuresLt(binbitop.getRightOperand(), precisionCall, 0, block, true)
96+
"The operand " + shift.getLeftOperand() + " is " + shift + "ed by a negative expression " +
97+
shift.getRightOperand() + "."
9998
) and
100-
message = "TODO"
101-
)
102-
}
99+
/*
100+
* Shift statement is not at a basic block where
101+
* `shift_rhs < PRECISION(...)` is ensured
102+
*/
103103

104-
predicate isForbiddenRShiftExpr(RShiftExpr binbitop, string message) {
105-
(
106-
(
107-
getPrecision(binbitop.getLeftOperand().getUnderlyingType()) <=
108-
upperBound(binbitop.getRightOperand()) and
109-
message =
110-
"The operand " + binbitop.getLeftOperand() + " is right-shifted by an expression " +
111-
binbitop.getRightOperand() + " which is greater than or equal to in precision."
112-
or
113-
lowerBound(binbitop.getRightOperand()) < 0 and
114-
message =
115-
"The operand " + binbitop.getLeftOperand() + " is right-shifted by a negative expression " +
116-
binbitop.getRightOperand() + "."
117-
)
118-
or
119-
/* Check a guard condition protecting the shift statement: heuristic (not an iff query) */
120-
exists(GuardCondition gc, BasicBlock block, Expr precisionCall |
121-
block = binbitop.getBasicBlock() and
104+
not exists(GuardCondition gc, BasicBlock block, Expr precisionCall, Expr lTLhs |
105+
block = shift.getBasicBlock() and
122106
(
123107
precisionCall.(FunctionCall).getTarget() instanceof PopCount
124108
or
125109
precisionCall = any(PrecisionMacro pm).getAnInvocation().getExpr()
126110
)
127111
|
128-
/*
129-
* Shift statement is at a basic block where
130-
* `shift_rhs < PRECISION(...)` is ensured
131-
*/
132-
133-
not gc.ensuresLt(binbitop.getRightOperand(), precisionCall, 0, block, true)
112+
globalValueNumber(lTLhs) = globalValueNumber(shift.getRightOperand()) and
113+
gc.ensuresLt(lTLhs, precisionCall, 0, block, true)
134114
) and
135-
message = "TODO"
115+
/*
116+
* Shift statement is not at a basic block where
117+
* `shift_rhs < 0` is ensured
118+
*/
119+
120+
not exists(GuardCondition gc, BasicBlock block, Expr literalZero, Expr lTLhs |
121+
block = shift.getBasicBlock() and
122+
literalZero instanceof LiteralZero
123+
|
124+
globalValueNumber(lTLhs) = globalValueNumber(shift.getRightOperand()) and
125+
gc.ensuresLt(lTLhs, literalZero, 0, block, true)
126+
)
136127
)
137128
}
138129

139130
from BinaryBitwiseOperation badShift, string message
140131
where
141132
not isExcluded(badShift, TypesPackage::exprShiftedbyNegativeOrGreaterPrecisionOperandQuery()) and
142-
isForbiddenLShiftExpr(badShift, message)
143-
or
144-
isForbiddenRShiftExpr(badShift, message)
133+
isForbiddenShiftExpr(badShift, message)
145134
select badShift, message

0 commit comments

Comments
 (0)