Skip to content

Commit 6699a0c

Browse files
committed
C++: Add range analysis for binary multiplication.
1 parent 12b236f commit 6699a0c

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,20 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10621062
or
10631063
upper = false and delta = D::fromFloat(-D::toFloat(d_max).abs() + 1)
10641064
)
1065+
or
1066+
exists(
1067+
SemZeroBound bLeft, SemZeroBound bRight, D::Delta dLeft, D::Delta dRight, boolean fbeLeft,
1068+
boolean fbeRight, D::Delta odLeft, D::Delta odRight, SemReason rLeft, SemReason rRight
1069+
|
1070+
boundedMulOperand(e, upper, bLeft, true, dLeft, fbeLeft, odLeft, rLeft) and
1071+
boundedMulOperand(e, upper, bRight, false, dRight, fbeRight, odRight, rRight) and
1072+
delta = D::fromFloat(D::toFloat(dLeft) * D::toFloat(dRight)) and
1073+
fromBackEdge = fbeLeft.booleanOr(fbeRight)
1074+
|
1075+
b = bLeft and origdelta = odLeft and reason = rLeft
1076+
or
1077+
b = bRight and origdelta = odRight and reason = rRight
1078+
)
10651079
)
10661080
}
10671081

@@ -1095,4 +1109,100 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10951109
) {
10961110
bounded(rem.getRightOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
10971111
}
1112+
1113+
/**
1114+
* Define `cmp(true) = <=` and `cmp(false) >=`.
1115+
*
1116+
* Holds if `mul = left * right`, and in order to know if `mul cmp(upper) B + k` (for
1117+
* some `B` and `k`) we need to know that `left cmp(upperLeft) B1 + k1` and
1118+
* `right cmp(upperRight) B2 + k2` (for some `B1`, `B2`, `k1`, and `k2`).
1119+
*/
1120+
pragma[nomagic]
1121+
private predicate boundedMulOperandCand(
1122+
SemMulExpr mul, SemExpr left, SemExpr right, boolean upper, boolean upperLeft,
1123+
boolean upperRight
1124+
) {
1125+
not boundFlowStepMul(mul, _, _) and
1126+
mul.getLeftOperand() = left and
1127+
mul.getRightOperand() = right and
1128+
(
1129+
semPositive(left) and
1130+
(
1131+
// left, right >= 0
1132+
semPositive(right) and
1133+
(
1134+
// max(left * right) = max(left) * max(right)
1135+
upper = true and
1136+
upperLeft = true and
1137+
upperRight = true
1138+
or
1139+
// min(left * right) = min(left) * min(right)
1140+
upper = false and
1141+
upperLeft = false and
1142+
upperRight = false
1143+
)
1144+
or
1145+
// left >= 0, right <= 0
1146+
semNegative(right) and
1147+
(
1148+
// max(left * right) = min(left) * max(right)
1149+
upper = true and
1150+
upperLeft = false and
1151+
upperRight = true
1152+
or
1153+
// min(left * right) = max(left) * min(right)
1154+
upper = false and
1155+
upperLeft = true and
1156+
upperRight = false
1157+
)
1158+
)
1159+
or
1160+
semNegative(left) and
1161+
(
1162+
// left <= 0, right >= 0
1163+
semPositive(right) and
1164+
(
1165+
// max(left * right) = max(left) * min(right)
1166+
upper = true and
1167+
upperLeft = true and
1168+
upperRight = false
1169+
or
1170+
// min(left * right) = min(left) * max(right)
1171+
upper = false and
1172+
upperLeft = false and
1173+
upperRight = true
1174+
)
1175+
or
1176+
// left, right <= 0
1177+
semNegative(right) and
1178+
(
1179+
// max(left * right) = min(left) * min(right)
1180+
upper = true and
1181+
upperLeft = false and
1182+
upperRight = false
1183+
or
1184+
// min(left * right) = max(left) * max(right)
1185+
upper = false and
1186+
upperLeft = true and
1187+
upperRight = true
1188+
)
1189+
)
1190+
)
1191+
}
1192+
1193+
pragma[nomagic]
1194+
private predicate boundedMulOperand(
1195+
SemMulExpr mul, boolean upper, SemZeroBound b, boolean isLeft, D::Delta delta,
1196+
boolean fromBackEdge, D::Delta origdelta, SemReason reason
1197+
) {
1198+
exists(boolean upperLeft, boolean upperRight, SemExpr left, SemExpr right |
1199+
boundedMulOperandCand(mul, left, right, upper, upperLeft, upperRight)
1200+
|
1201+
isLeft = true and
1202+
bounded(left, b, delta, upperLeft, fromBackEdge, origdelta, reason)
1203+
or
1204+
isLeft = false and
1205+
bounded(right, b, delta, upperRight, fromBackEdge, origdelta, reason)
1206+
)
1207+
}
10981208
}

0 commit comments

Comments
 (0)