Skip to content

Commit 9810a4f

Browse files
committed
C++: Remove 'inNonZeroCase' from IRGuards since we now always have implicit comparisons against 0 in C code.
1 parent 0d7adac commit 9810a4f

File tree

1 file changed

+25
-76
lines changed

1 file changed

+25
-76
lines changed

cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll

Lines changed: 25 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ class IRGuardCondition extends Instruction {
588588
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
589589
pragma[inline]
590590
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
591-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value)
591+
unary_compares_eq(valueNumber(this), op, k, areEqual, value)
592592
}
593593

594594
/**
@@ -610,7 +610,7 @@ class IRGuardCondition extends Instruction {
610610
pragma[inline]
611611
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
612612
exists(AbstractValue value |
613-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
613+
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
614614
this.valueControls(block, value)
615615
)
616616
}
@@ -636,7 +636,7 @@ class IRGuardCondition extends Instruction {
636636
pragma[inline]
637637
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
638638
exists(AbstractValue value |
639-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
639+
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
640640
this.valueControlsEdge(pred, succ, value)
641641
)
642642
}
@@ -849,75 +849,35 @@ private module Cached {
849849

850850
/**
851851
* Holds if `op == k` is `areEqual` given that `test` is equal to `value`.
852-
*
853-
* Many internal predicates in this file have a `inNonZeroCase` column.
854-
* Ideally, the `k` column would be a type such as `Option<int>::Option`, to
855-
* represent whether we have a concrete value `k` such that `op == k`, or whether
856-
* we only know that `op != 0`.
857-
* However, cannot instantiate `Option` with an infinite type. Thus the boolean
858-
* `inNonZeroCase` is used to distinquish the `Some` (where we have a concrete
859-
* value `k`) and `None` cases (where we only know that `op != 0`).
860-
*
861-
* Thus, if `inNonZeroCase = true` then `op != 0` and the value of `k` is
862-
* meaningless.
863-
*
864-
* To see why `inNonZeroCase` is needed consider the following C program:
865-
* ```c
866-
* char* p = ...;
867-
* if(p) {
868-
* use(p);
869-
* }
870-
* ```
871-
* in C++ there would be an int-to-bool conversion on `p`. However, since C
872-
* does not have booleans there is no conversion. We want to be able to
873-
* conclude that `p` is non-zero in the true branch, so we need to give `k`
874-
* some value. However, simply setting `k = 1` would make the rest of the
875-
* analysis think that `k == 1` holds inside the branch. So we distinquish
876-
* between the above case and
877-
* ```c
878-
* if(p == 1) {
879-
* use(p)
880-
* }
881-
* ```
882-
* by setting `inNonZeroCase` to `true` in the former case, but not in the
883-
* latter.
884852
*/
885853
cached
886854
predicate unary_compares_eq(
887-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
888-
AbstractValue value
855+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
889856
) {
890857
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
891-
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
858+
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, v) |
892859
areEqual = true and value = v
893860
or
894861
areEqual = false and value = v.getDualValue()
895862
)
896863
or
897-
unary_complex_eq(test, op, k, areEqual, inNonZeroCase, value)
864+
unary_complex_eq(test, op, k, areEqual, value)
898865
or
899866
/* (x is true => (op == k)) => (!x is false => (op == k)) */
900-
exists(AbstractValue dual, boolean inNonZeroCase0 |
867+
exists(AbstractValue dual |
901868
value = dual.getDualValue() and
902-
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, inNonZeroCase0, areEqual,
903-
dual)
904-
|
905-
k = 0 and inNonZeroCase = inNonZeroCase0
906-
or
907-
k != 0 and inNonZeroCase = true
869+
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, areEqual, dual)
908870
)
909871
or
910872
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
911873
// test is `areEqual` => op == k1 + k2
912-
inNonZeroCase = false and
913874
exists(int k1, int k2, Instruction const |
914875
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
915876
int_value(const) = k1 and
916877
k = k1 + k2
917878
)
918879
or
919-
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual,
920-
inNonZeroCase, value)
880+
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual, value)
921881
}
922882

923883
/** Rearrange various simple comparisons into `left == right + k` form. */
@@ -986,27 +946,24 @@ private module Cached {
986946

987947
/** Rearrange various simple comparisons into `op == k` form. */
988948
private predicate unary_simple_comparison_eq(
989-
ValueNumber test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
949+
ValueNumber test, Operand op, int k, AbstractValue value
990950
) {
991951
exists(CaseEdge case, SwitchConditionValueNumber condition |
992952
condition = test and
993953
op = condition.getExpressionOperand() and
994954
case = value.(MatchValue).getCase() and
995955
exists(condition.getSuccessor(case)) and
996-
case.getValue().toInt() = k and
997-
inNonZeroCase = false
956+
case.getValue().toInt() = k
998957
)
999958
or
1000959
isRelevantUnaryComparisonOperand(op) and
1001960
op.getDef() = test.getAnInstruction() and
1002961
(
1003962
k = 1 and
1004-
value.(BooleanValue).getValue() = true and
1005-
inNonZeroCase = true
963+
value.(BooleanValue).getValue() = true
1006964
or
1007965
k = 0 and
1008-
value.(BooleanValue).getValue() = false and
1009-
inNonZeroCase = false
966+
value.(BooleanValue).getValue() = false
1010967
)
1011968
}
1012969

@@ -1061,13 +1018,12 @@ private module Cached {
10611018
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
10621019
*/
10631020
private predicate unary_builtin_expect_eq(
1064-
CompareValueNumber cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
1065-
AbstractValue value
1021+
CompareValueNumber cmp, Operand op, int k, boolean areEqual, AbstractValue value
10661022
) {
10671023
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
10681024
int_value(const) = 0 and
10691025
cmp.hasOperands(call.getAUse(), const.getAUse()) and
1070-
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
1026+
unary_compares_eq(call.getCondition(), op, k, areEqual, innerValue)
10711027
|
10721028
cmp instanceof CompareNEValueNumber and
10731029
value = innerValue
@@ -1078,14 +1034,13 @@ private module Cached {
10781034
}
10791035

10801036
private predicate unary_complex_eq(
1081-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
1082-
AbstractValue value
1037+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
10831038
) {
1084-
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
1039+
unary_sub_eq(test, op, k, areEqual, value)
10851040
or
1086-
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
1041+
unary_add_eq(test, op, k, areEqual, value)
10871042
or
1088-
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
1043+
unary_builtin_expect_eq(test, op, k, areEqual, value)
10891044
}
10901045

10911046
/*
@@ -1347,20 +1302,17 @@ private module Cached {
13471302

13481303
// op - x == c => op == (c+x)
13491304
private predicate unary_sub_eq(
1350-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
1351-
AbstractValue value
1305+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
13521306
) {
1353-
inNonZeroCase = false and
13541307
exists(SubInstruction sub, int c, int x |
1355-
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
1308+
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
13561309
op = sub.getLeftOperand() and
13571310
x = int_value(sub.getRight()) and
13581311
k = c + x
13591312
)
13601313
or
1361-
inNonZeroCase = false and
13621314
exists(PointerSubInstruction sub, int c, int x |
1363-
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
1315+
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
13641316
op = sub.getLeftOperand() and
13651317
x = int_value(sub.getRight()) and
13661318
k = c + x
@@ -1415,12 +1367,10 @@ private module Cached {
14151367

14161368
// left + x == right + c => left == right + (c-x)
14171369
private predicate unary_add_eq(
1418-
ValueNumber test, Operand left, int k, boolean areEqual, boolean inNonZeroCase,
1419-
AbstractValue value
1370+
ValueNumber test, Operand left, int k, boolean areEqual, AbstractValue value
14201371
) {
1421-
inNonZeroCase = false and
14221372
exists(AddInstruction lhs, int c, int x |
1423-
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
1373+
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
14241374
(
14251375
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
14261376
or
@@ -1429,9 +1379,8 @@ private module Cached {
14291379
k = c - x
14301380
)
14311381
or
1432-
inNonZeroCase = false and
14331382
exists(PointerAddInstruction lhs, int c, int x |
1434-
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
1383+
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
14351384
(
14361385
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
14371386
or

0 commit comments

Comments
 (0)