Skip to content

Commit 9787712

Browse files
committed
C++: Remove the 'inNonZeroCase' column.
1 parent dc46d45 commit 9787712

File tree

4 files changed

+519
-72
lines changed

4 files changed

+519
-72
lines changed

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

Lines changed: 25 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ class IRGuardCondition extends Instruction {
681681
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
682682
cached
683683
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
684-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value)
684+
unary_compares_eq(valueNumber(this), op, k, areEqual, value)
685685
}
686686

687687
/**
@@ -703,7 +703,7 @@ class IRGuardCondition extends Instruction {
703703
cached
704704
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
705705
exists(AbstractValue value |
706-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
706+
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
707707
this.valueControls(block, value)
708708
)
709709
}
@@ -729,7 +729,7 @@ class IRGuardCondition extends Instruction {
729729
cached
730730
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
731731
exists(AbstractValue value |
732-
unary_compares_eq(valueNumber(this), op, k, areEqual, false, value) and
732+
unary_compares_eq(valueNumber(this), op, k, areEqual, value) and
733733
this.valueControlsEdge(pred, succ, value)
734734
)
735735
}
@@ -866,72 +866,34 @@ private predicate compares_eq(
866866

867867
/**
868868
* Holds if `op == k` is `areEqual` given that `test` is equal to `value`.
869-
*
870-
* Many internal predicates in this file have a `inNonZeroCase` column.
871-
* Ideally, the `k` column would be a type such as `Option<int>::Option`, to
872-
* represent whether we have a concrete value `k` such that `op == k`, or whether
873-
* we only know that `op != 0`.
874-
* However, cannot instantiate `Option` with an infinite type. Thus the boolean
875-
* `inNonZeroCase` is used to distinquish the `Some` (where we have a concrete
876-
* value `k`) and `None` cases (where we only know that `op != 0`).
877-
*
878-
* Thus, if `inNonZeroCase = true` then `op != 0` and the value of `k` is
879-
* meaningless.
880-
*
881-
* To see why `inNonZeroCase` is needed consider the following C program:
882-
* ```c
883-
* char* p = ...;
884-
* if(p) {
885-
* use(p);
886-
* }
887-
* ```
888-
* in C++ there would be an int-to-bool conversion on `p`. However, since C
889-
* does not have booleans there is no conversion. We want to be able to
890-
* conclude that `p` is non-zero in the true branch, so we need to give `k`
891-
* some value. However, simply setting `k = 1` would make the rest of the
892-
* analysis think that `k == 1` holds inside the branch. So we distinquish
893-
* between the above case and
894-
* ```c
895-
* if(p == 1) {
896-
* use(p)
897-
* }
898-
* ```
899-
* by setting `inNonZeroCase` to `true` in the former case, but not in the
900-
* latter.
901869
*/
902870
private predicate unary_compares_eq(
903-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
871+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
904872
) {
905873
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
906-
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
874+
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, v) |
907875
areEqual = true and value = v
908876
or
909877
areEqual = false and value = v.getDualValue()
910878
)
911879
or
912-
unary_complex_eq(test, op, k, areEqual, inNonZeroCase, value)
880+
unary_complex_eq(test, op, k, areEqual, value)
913881
or
914882
/* (x is true => (op == k)) => (!x is false => (op == k)) */
915-
exists(AbstractValue dual, boolean inNonZeroCase0 |
883+
exists(AbstractValue dual |
916884
value = dual.getDualValue() and
917-
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, inNonZeroCase0, areEqual, dual)
918-
|
919-
k = 0 and inNonZeroCase = inNonZeroCase0
920-
or
921-
k != 0 and inNonZeroCase = true
885+
unary_compares_eq(test.(LogicalNotValueNumber).getUnary(), op, k, areEqual, dual)
922886
)
923887
or
924888
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
925889
// test is `areEqual` => op == k1 + k2
926-
inNonZeroCase = false and
927890
exists(int k1, int k2, Instruction const |
928891
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
929892
int_value(const) = k1 and
930893
k = k1 + k2
931894
)
932895
or
933-
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual,
934-
inNonZeroCase, value)
896+
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual, value)
935897
}
936898

937899
/** Rearrange various simple comparisons into `left == right + k` form. */
@@ -1000,27 +962,24 @@ private predicate isRelevantUnaryComparisonOperand(Operand op) {
1000962

1001963
/** Rearrange various simple comparisons into `op == k` form. */
1002964
private predicate unary_simple_comparison_eq(
1003-
ValueNumber test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
965+
ValueNumber test, Operand op, int k, AbstractValue value
1004966
) {
1005967
exists(CaseEdge case, SwitchConditionValueNumber condition |
1006968
condition = test and
1007969
op = condition.getExpressionOperand() and
1008970
case = value.(MatchValue).getCase() and
1009971
exists(condition.getSuccessor(case)) and
1010-
case.getValue().toInt() = k and
1011-
inNonZeroCase = false
972+
case.getValue().toInt() = k
1012973
)
1013974
or
1014975
isRelevantUnaryComparisonOperand(op) and
1015976
op.getDef() = test.getAnInstruction() and
1016977
(
1017978
k = 1 and
1018-
value.(BooleanValue).getValue() = true and
1019-
inNonZeroCase = true
979+
value.(BooleanValue).getValue() = true
1020980
or
1021981
k = 0 and
1022-
value.(BooleanValue).getValue() = false and
1023-
inNonZeroCase = false
982+
value.(BooleanValue).getValue() = false
1024983
)
1025984
}
1026985

@@ -1074,13 +1033,12 @@ private predicate complex_eq(
10741033
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
10751034
*/
10761035
private predicate unary_builtin_expect_eq(
1077-
CompareValueNumber cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
1078-
AbstractValue value
1036+
CompareValueNumber cmp, Operand op, int k, boolean areEqual, AbstractValue value
10791037
) {
10801038
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
10811039
int_value(const) = 0 and
10821040
cmp.hasOperands(call.getAUse(), const.getAUse()) and
1083-
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
1041+
unary_compares_eq(call.getCondition(), op, k, areEqual, innerValue)
10841042
|
10851043
cmp instanceof CompareNEValueNumber and
10861044
value = innerValue
@@ -1091,13 +1049,13 @@ private predicate unary_builtin_expect_eq(
10911049
}
10921050

10931051
private predicate unary_complex_eq(
1094-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
1052+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
10951053
) {
1096-
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
1054+
unary_sub_eq(test, op, k, areEqual, value)
10971055
or
1098-
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
1056+
unary_add_eq(test, op, k, areEqual, value)
10991057
or
1100-
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
1058+
unary_builtin_expect_eq(test, op, k, areEqual, value)
11011059
}
11021060

11031061
/*
@@ -1357,19 +1315,17 @@ private predicate sub_eq(
13571315

13581316
// op - x == c => op == (c+x)
13591317
private predicate unary_sub_eq(
1360-
ValueNumber test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
1318+
ValueNumber test, Operand op, int k, boolean areEqual, AbstractValue value
13611319
) {
1362-
inNonZeroCase = false and
13631320
exists(SubInstruction sub, int c, int x |
1364-
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
1321+
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
13651322
op = sub.getLeftOperand() and
13661323
x = int_value(sub.getRight()) and
13671324
k = c + x
13681325
)
13691326
or
1370-
inNonZeroCase = false and
13711327
exists(PointerSubInstruction sub, int c, int x |
1372-
unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
1328+
unary_compares_eq(test, sub.getAUse(), c, areEqual, value) and
13731329
op = sub.getLeftOperand() and
13741330
x = int_value(sub.getRight()) and
13751331
k = c + x
@@ -1424,12 +1380,10 @@ private predicate add_eq(
14241380

14251381
// left + x == right + c => left == right + (c-x)
14261382
private predicate unary_add_eq(
1427-
ValueNumber test, Operand left, int k, boolean areEqual, boolean inNonZeroCase,
1428-
AbstractValue value
1383+
ValueNumber test, Operand left, int k, boolean areEqual, AbstractValue value
14291384
) {
1430-
inNonZeroCase = false and
14311385
exists(AddInstruction lhs, int c, int x |
1432-
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
1386+
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
14331387
(
14341388
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
14351389
or
@@ -1438,9 +1392,8 @@ private predicate unary_add_eq(
14381392
k = c - x
14391393
)
14401394
or
1441-
inNonZeroCase = false and
14421395
exists(PointerAddInstruction lhs, int c, int x |
1443-
unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
1396+
unary_compares_eq(test, lhs.getAUse(), c, areEqual, value) and
14441397
(
14451398
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
14461399
or

0 commit comments

Comments
 (0)