Skip to content

Commit 2a02ce1

Browse files
committed
C++: Fix join orders in 'exprIsSubLeftOrLess'.
Before: Tuple counts for UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff/2@i3#a5071w3a after 24s: 304220 ~2% {2} r1 = JOIN UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff#prev_delta WITH Expr::BinaryOperation#class#f#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.0 'sub' 190061335 ~24% {2} r2 = JOIN r1 WITH DataFlowUtil::localFlowStep#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 3956 ~0% {2} r3 = JOIN r1 WITH DataFlowUtil::localFlowStep#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 407983 ~1% {2} r4 = JOIN Expr::BinaryOperation#class#f#join_rhs WITH UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff#prev ON FIRST 1 OUTPUT Rhs.1 'n', Lhs.0 'sub' 380823 ~0% {2} r5 = JOIN r4 WITH DataFlowUtil::TExprNode#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 0 ~0% {2} r6 = JOIN r5 WITH UnsignedDifferenceExpressionComparedZero::isGuarded#fff#prev_delta ON FIRST 2 OUTPUT Rhs.2, Lhs.0 'sub' 0 ~0% {2} r7 = JOIN r6 WITH DataFlowUtil::TExprNode#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 3956 ~0% {2} r8 = r3 UNION r7 190065291 ~24% {2} r9 = r2 UNION r8 ... After: Tuple counts for UnsignedDifferenceExpressionComparedZero::interestingSubExpr#f/1@654e29g3 after 228ms: 370 ~2% {2} r1 = ComparisonOperation::RelationalOperation::getGreaterOperand_dispred#fb AND NOT Exclusions::isFromMacroDefinition#b(Lhs.1 'sub') 370 ~0% {2} r2 = SCAN r1 OUTPUT In.1 'sub', In.0 370 ~3% {3} r3 = JOIN r2 WITH Expr::Expr::getFullyConverted_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0 'sub' 210 ~1% {2} r4 = JOIN r3 WITH SimpleRangeAnalysis::SimpleRangeAnalysisCached::exprMightOverflowNegatively#f ON FIRST 1 OUTPUT Lhs.2 'sub', Lhs.1 210 ~0% {3} r5 = JOIN r4 WITH Expr::Expr::getFullyConverted_dispred#ff ON FIRST 1 OUTPUT Lhs.1, Lhs.0 'sub', Rhs.1 210 ~1% {3} r6 = JOIN r5 WITH ComparisonOperation::RelationalOperation::getLesserOperand_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'sub', Lhs.2 59 ~2% {4} r7 = JOIN r6 WITH Expr::Expr::getValue_dispred#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Lhs.2, Rhs.1, toInt(Rhs.1) 17 ~0% {4} r8 = SELECT r7 ON In.3 = 0 17 ~0% {2} r9 = SCAN r8 OUTPUT In.1, In.0 'sub' 8 ~0% {2} r10 = JOIN r9 WITH Expr::Expr::getUnspecifiedType_dispred#bb ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'sub' 8 ~0% {1} r11 = JOIN r10 WITH Type::IntegralType::isUnsigned_dispred#f ON FIRST 1 OUTPUT Lhs.1 'sub' return r11 Tuple counts for UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff/2@i2#61800weu after 1ms: 8 ~0% {2} r1 = JOIN UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff#prev_delta WITH UnsignedDifferenceExpressionComparedZero::interestingSubExpr#f ON FIRST 1 OUTPUT Lhs.1, Lhs.0 'sub' 0 ~0% {2} r2 = JOIN r1 WITH DataFlowUtil::localFlowStep#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 1 ~0% {2} r3 = JOIN r1 WITH DataFlowUtil::localFlowStep#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 0 ~0% {3} r4 = JOIN UnsignedDifferenceExpressionComparedZero::isGuarded#fff#prev_delta WITH UnsignedDifferenceExpressionComparedZero::interestingSubExpr#f ON FIRST 1 OUTPUT Lhs.1, Lhs.0 'sub', Lhs.2 0 ~0% {3} r5 = JOIN r4 WITH DataFlowUtil::TExprNode#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n', Lhs.2 0 ~0% {2} r6 = JOIN r5 WITH UnsignedDifferenceExpressionComparedZero::exprIsSubLeftOrLess#ff#prev ON FIRST 2 OUTPUT Lhs.2, Lhs.0 'sub' 0 ~0% {2} r7 = JOIN r6 WITH DataFlowUtil::TExprNode#ff ON FIRST 1 OUTPUT Lhs.1 'sub', Rhs.1 'n' 1 ~0% {2} r8 = r3 UNION r7 1 ~0% {2} r9 = r2 UNION r8 ...
1 parent f2d6bcd commit 2a02ce1

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,47 +38,56 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
3838
* `sub.getLeftOperand()`.
3939
*/
4040
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
41-
n.asExpr() = sub.getLeftOperand()
42-
or
43-
exists(DataFlow::Node other |
44-
// dataflow
45-
exprIsSubLeftOrLess(sub, other) and
46-
(
47-
DataFlow::localFlowStep(n, other) or
48-
DataFlow::localFlowStep(other, n)
41+
interestingSubExpr(sub, _) and // Manual magic
42+
(
43+
n.asExpr() = sub.getLeftOperand()
44+
or
45+
exists(DataFlow::Node other |
46+
// dataflow
47+
exprIsSubLeftOrLess(sub, other) and
48+
(
49+
DataFlow::localFlowStep(n, other) or
50+
DataFlow::localFlowStep(other, n)
51+
)
52+
)
53+
or
54+
exists(DataFlow::Node other |
55+
// guard constraining `sub`
56+
exprIsSubLeftOrLess(sub, other) and
57+
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
58+
)
59+
or
60+
exists(DataFlow::Node other, float p, float q |
61+
// linear access of `other`
62+
exprIsSubLeftOrLess(sub, other) and
63+
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
64+
p <= 1 and
65+
q <= 0
66+
)
67+
or
68+
exists(DataFlow::Node other, float p, float q |
69+
// linear access of `n`
70+
exprIsSubLeftOrLess(sub, other) and
71+
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
72+
p >= 1 and
73+
q >= 0
4974
)
50-
)
51-
or
52-
exists(DataFlow::Node other |
53-
// guard constraining `sub`
54-
exprIsSubLeftOrLess(sub, other) and
55-
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
56-
)
57-
or
58-
exists(DataFlow::Node other, float p, float q |
59-
// linear access of `other`
60-
exprIsSubLeftOrLess(sub, other) and
61-
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
62-
p <= 1 and
63-
q <= 0
64-
)
65-
or
66-
exists(DataFlow::Node other, float p, float q |
67-
// linear access of `n`
68-
exprIsSubLeftOrLess(sub, other) and
69-
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
70-
p >= 1 and
71-
q >= 0
7275
)
7376
}
7477

75-
from RelationalOperation ro, SubExpr sub
76-
where
77-
not isFromMacroDefinition(ro) and
78+
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {
7879
not isFromMacroDefinition(sub) and
7980
ro.getLesserOperand().getValue().toInt() = 0 and
8081
ro.getGreaterOperand() = sub and
8182
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
82-
exprMightOverflowNegatively(sub.getFullyConverted()) and // generally catches false positives involving constants
83-
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand())) // generally catches false positives where there's a relation between the left and right operands
83+
// generally catches false positives involving constants
84+
exprMightOverflowNegatively(sub.getFullyConverted())
85+
}
86+
87+
from RelationalOperation ro, SubExpr sub
88+
where
89+
interestingSubExpr(sub, ro) and
90+
not isFromMacroDefinition(ro) and
91+
// generally catches false positives where there's a relation between the left and right operands
92+
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand()))
8493
select ro, "Unsigned subtraction can never be negative."

0 commit comments

Comments
 (0)