Skip to content

Commit e12b5be

Browse files
committed
C++: Generalize more predicates from booleans to abstract values.
1 parent 7429fa7 commit e12b5be

File tree

2 files changed

+42
-30
lines changed

2 files changed

+42
-30
lines changed

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

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,10 @@ class IRGuardCondition extends Instruction {
446446
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
447447
cached
448448
predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
449-
compares_eq(this, left, right, k, areEqual, testIsTrue)
449+
exists(BooleanValue value |
450+
compares_eq(this, left, right, k, areEqual, value) and
451+
value.getValue() = testIsTrue
452+
)
450453
}
451454

452455
/**
@@ -455,8 +458,8 @@ class IRGuardCondition extends Instruction {
455458
*/
456459
cached
457460
predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
458-
exists(boolean testIsTrue |
459-
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
461+
exists(AbstractValue value |
462+
compares_eq(this, left, right, k, areEqual, value) and this.valueControls(block, value)
460463
)
461464
}
462465

@@ -468,9 +471,9 @@ class IRGuardCondition extends Instruction {
468471
predicate ensuresEqEdge(
469472
Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual
470473
) {
471-
exists(boolean testIsTrue |
472-
compares_eq(this, left, right, k, areEqual, testIsTrue) and
473-
this.controlsEdge(pred, succ, testIsTrue)
474+
exists(AbstractValue value |
475+
compares_eq(this, left, right, k, areEqual, value) and
476+
this.valueControlsEdge(pred, succ, value)
474477
)
475478
}
476479

@@ -572,52 +575,52 @@ private Instruction getBranchForCondition(Instruction guard) {
572575
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
573576
*/
574577
private predicate compares_eq(
575-
Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
578+
Instruction test, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
576579
) {
577580
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
578-
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
579-
areEqual = true and testIsTrue = eq
581+
exists(AbstractValue v | simple_comparison_eq(test, left, right, k, v) |
582+
areEqual = true and value = v
580583
or
581-
areEqual = false and testIsTrue = eq.booleanNot()
584+
areEqual = false and value = v.getDualValue()
582585
)
583586
or
584587
// I think this is handled by forwarding in controlsBlock.
585588
//or
586589
//logical_comparison_eq(test, left, right, k, areEqual, testIsTrue)
587590
/* a == b + k => b == a - k */
588-
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue))
591+
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, value))
589592
or
590-
complex_eq(test, left, right, k, areEqual, testIsTrue)
593+
complex_eq(test, left, right, k, areEqual, value)
591594
or
592595
/* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */
593-
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
594-
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, isFalse)
596+
exists(AbstractValue dual | value = dual.getDualValue() |
597+
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
595598
)
596599
}
597600

598601
/** Rearrange various simple comparisons into `left == right + k` form. */
599602
private predicate simple_comparison_eq(
600-
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual
603+
CompareInstruction cmp, Operand left, Operand right, int k, AbstractValue value
601604
) {
602605
left = cmp.getLeftOperand() and
603606
cmp instanceof CompareEQInstruction and
604607
right = cmp.getRightOperand() and
605608
k = 0 and
606-
areEqual = true
609+
value.(BooleanValue).getValue() = true
607610
or
608611
left = cmp.getLeftOperand() and
609612
cmp instanceof CompareNEInstruction and
610613
right = cmp.getRightOperand() and
611614
k = 0 and
612-
areEqual = false
615+
value.(BooleanValue).getValue() = false
613616
}
614617

615618
private predicate complex_eq(
616-
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
619+
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
617620
) {
618-
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
621+
sub_eq(cmp, left, right, k, areEqual, value)
619622
or
620-
add_eq(cmp, left, right, k, areEqual, testIsTrue)
623+
add_eq(cmp, left, right, k, areEqual, value)
621624
}
622625

623626
/*
@@ -768,31 +771,31 @@ private predicate add_lt(
768771
// left - x == right + c => left == right + (c+x)
769772
// left == (right - x) + c => left == right + (c-x)
770773
private predicate sub_eq(
771-
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
774+
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
772775
) {
773776
exists(SubInstruction lhs, int c, int x |
774-
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
777+
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
775778
left = lhs.getLeftOperand() and
776779
x = int_value(lhs.getRight()) and
777780
k = c + x
778781
)
779782
or
780783
exists(SubInstruction rhs, int c, int x |
781-
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
784+
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
782785
right = rhs.getLeftOperand() and
783786
x = int_value(rhs.getRight()) and
784787
k = c - x
785788
)
786789
or
787790
exists(PointerSubInstruction lhs, int c, int x |
788-
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
791+
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
789792
left = lhs.getLeftOperand() and
790793
x = int_value(lhs.getRight()) and
791794
k = c + x
792795
)
793796
or
794797
exists(PointerSubInstruction rhs, int c, int x |
795-
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
798+
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
796799
right = rhs.getLeftOperand() and
797800
x = int_value(rhs.getRight()) and
798801
k = c - x
@@ -802,10 +805,10 @@ private predicate sub_eq(
802805
// left + x == right + c => left == right + (c-x)
803806
// left == (right + x) + c => left == right + (c+x)
804807
private predicate add_eq(
805-
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
808+
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
806809
) {
807810
exists(AddInstruction lhs, int c, int x |
808-
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
811+
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
809812
(
810813
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
811814
or
@@ -815,7 +818,7 @@ private predicate add_eq(
815818
)
816819
or
817820
exists(AddInstruction rhs, int c, int x |
818-
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
821+
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
819822
(
820823
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
821824
or
@@ -825,7 +828,7 @@ private predicate add_eq(
825828
)
826829
or
827830
exists(PointerAddInstruction lhs, int c, int x |
828-
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
831+
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
829832
(
830833
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
831834
or
@@ -835,7 +838,7 @@ private predicate add_eq(
835838
)
836839
or
837840
exists(PointerAddInstruction rhs, int c, int x |
838-
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
841+
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
839842
(
840843
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
841844
or

cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ class CaseEdge extends EdgeKind, TCaseEdge {
9090
* Gets the largest value of the switch expression for which control will flow along this edge.
9191
*/
9292
final string getMaxValue() { result = maxValue }
93+
94+
/**
95+
* Gets the unique value of ther switch expression for which control will
96+
* flow alogn this edge, if any.
97+
*/
98+
final string getValue() {
99+
minValue = maxValue and
100+
result = minValue
101+
}
93102
}
94103

95104
/**

0 commit comments

Comments
 (0)