@@ -15,91 +15,8 @@ import codingstandards.c.cert
1515import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1616import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1717import semmle.code.cpp.controlflow.Guards
18+ import codingstandards.cpp.UndefinedBehavior
1819
19- /*
20- * Precision predicate based on a sample implementation from
21- * https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Use+correct+integer+precisions
22- */
23-
24- /**
25- * A function whose name is suggestive that it counts the number of bits set.
26- */
27- class PopCount extends Function {
28- PopCount ( ) { this .getName ( ) .toLowerCase ( ) .matches ( "%popc%nt%" ) }
29- }
30-
31- /**
32- * A macro which is suggestive that it is used to determine the precision of an integer.
33- */
34- class PrecisionMacro extends Macro {
35- PrecisionMacro ( ) { this .getName ( ) .toLowerCase ( ) .matches ( "precision" ) }
36- }
37-
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-
49- int getPrecision ( IntegralType type ) {
50- type .isExplicitlyUnsigned ( ) and result = type .getSize ( ) * 8
51- or
52- type .isExplicitlySigned ( ) and result = type .getSize ( ) * 8 - 1
53- }
54-
55- predicate isForbiddenShiftExpr ( BitShiftExpr shift , string message ) {
56- (
57- (
58- getPrecision ( shift .getLeftOperand ( ) .getExplicitlyConverted ( ) .getUnderlyingType ( ) ) <=
59- upperBound ( shift .getRightOperand ( ) ) and
60- message =
61- "The operand " + shift .getLeftOperand ( ) + " is shifted by an expression " +
62- shift .getRightOperand ( ) + " whose upper bound (" + upperBound ( shift .getRightOperand ( ) ) +
63- ") is greater than or equal to the precision."
64- or
65- lowerBound ( shift .getRightOperand ( ) ) < 0 and
66- message =
67- "The operand " + shift .getLeftOperand ( ) + " is shifted by an expression " +
68- shift .getRightOperand ( ) + " which may be negative."
69- ) and
70- /*
71- * Shift statement is not at a basic block where
72- * `shift_rhs < PRECISION(...)` is ensured
73- */
74-
75- not exists ( GuardCondition gc , BasicBlock block , Expr precisionCall , Expr lTLhs |
76- block = shift .getBasicBlock ( ) and
77- (
78- precisionCall .( FunctionCall ) .getTarget ( ) instanceof PopCount
79- or
80- precisionCall = any ( PrecisionMacro pm ) .getAnInvocation ( ) .getExpr ( )
81- )
82- |
83- globalValueNumber ( lTLhs ) = globalValueNumber ( shift .getRightOperand ( ) ) and
84- gc .ensuresLt ( lTLhs , precisionCall , 0 , block , true )
85- ) and
86- /*
87- * Shift statement is not at a basic block where
88- * `shift_rhs < 0` is ensured
89- */
90-
91- not exists ( GuardCondition gc , BasicBlock block , Expr literalZero , Expr lTLhs |
92- block = shift .getBasicBlock ( ) and
93- literalZero instanceof LiteralZero
94- |
95- globalValueNumber ( lTLhs ) = globalValueNumber ( shift .getRightOperand ( ) ) and
96- gc .ensuresLt ( lTLhs , literalZero , 0 , block , true )
97- )
98- )
99- }
100-
101- from BinaryBitwiseOperation badShift , string message
102- where
103- not isExcluded ( badShift , Types1Package:: exprShiftedbyNegativeOrGreaterPrecisionOperandQuery ( ) ) and
104- isForbiddenShiftExpr ( badShift , message )
105- select badShift , message
20+ from ShiftByNegativeOrGreaterPrecisionOperand badShift
21+ where not isExcluded ( badShift , Types1Package:: exprShiftedbyNegativeOrGreaterPrecisionOperandQuery ( ) )
22+ select badShift , badShift .getReason ( )
0 commit comments