@@ -651,13 +651,16 @@ predicate jumpStep(Node n1, Node n2) {
651
651
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
652
652
* Thus, `node2` references an object with a field `f` that contains the
653
653
* value of `node1`.
654
+ *
655
+ * The boolean `certain` is true if the destination address does not involve
656
+ * any pointer arithmetic, and false otherwise.
654
657
*/
655
- predicate storeStep ( Node node1 , Content c , PostFieldUpdateNode node2 ) {
658
+ predicate storeStepImpl ( Node node1 , Content c , PostFieldUpdateNode node2 , boolean certain ) {
656
659
exists ( int indirectionIndex1 , int numberOfLoads , StoreInstruction store |
657
660
nodeHasInstruction ( node1 , store , pragma [ only_bind_into ] ( indirectionIndex1 ) ) and
658
661
node2 .getIndirectionIndex ( ) = 1 and
659
662
numberOfLoadsFromOperand ( node2 .getFieldAddress ( ) , store .getDestinationAddressOperand ( ) ,
660
- numberOfLoads )
663
+ numberOfLoads , certain )
661
664
|
662
665
exists ( FieldContent fc | fc = c |
663
666
fc .getField ( ) = node2 .getUpdatedField ( ) and
@@ -671,35 +674,51 @@ predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
671
674
)
672
675
}
673
676
677
+ /**
678
+ * Holds if data can flow from `node1` to `node2` via an assignment to `f`.
679
+ * Thus, `node2` references an object with a field `f` that contains the
680
+ * value of `node1`.
681
+ */
682
+ predicate storeStep ( Node node1 , Content c , PostFieldUpdateNode node2 ) {
683
+ storeStepImpl ( node1 , c , node2 , _)
684
+ }
685
+
674
686
/**
675
687
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
676
688
* operations and exactly `n` `LoadInstruction` operations.
677
689
*/
678
- private predicate numberOfLoadsFromOperandRec ( Operand operandFrom , Operand operandTo , int ind ) {
690
+ private predicate numberOfLoadsFromOperandRec (
691
+ Operand operandFrom , Operand operandTo , int ind , boolean certain
692
+ ) {
679
693
exists ( Instruction load | Ssa:: isDereference ( load , operandFrom ) |
680
- operandTo = operandFrom and ind = 0
694
+ operandTo = operandFrom and ind = 0 and certain = true
681
695
or
682
- numberOfLoadsFromOperand ( load .getAUse ( ) , operandTo , ind - 1 )
696
+ numberOfLoadsFromOperand ( load .getAUse ( ) , operandTo , ind - 1 , certain )
683
697
)
684
698
or
685
- exists ( Operand op , Instruction instr |
699
+ exists ( Operand op , Instruction instr , boolean isPointerArith , boolean certain0 |
686
700
instr = op .getDef ( ) and
687
- conversionFlow ( operandFrom , instr , _, _) and
688
- numberOfLoadsFromOperand ( op , operandTo , ind )
701
+ conversionFlow ( operandFrom , instr , isPointerArith , _) and
702
+ numberOfLoadsFromOperand ( op , operandTo , ind , certain0 )
703
+ |
704
+ if isPointerArith = true then certain = false else certain = certain0
689
705
)
690
706
}
691
707
692
708
/**
693
709
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
694
710
* operations and exactly `n` `LoadInstruction` operations.
695
711
*/
696
- private predicate numberOfLoadsFromOperand ( Operand operandFrom , Operand operandTo , int n ) {
697
- numberOfLoadsFromOperandRec ( operandFrom , operandTo , n )
712
+ private predicate numberOfLoadsFromOperand (
713
+ Operand operandFrom , Operand operandTo , int n , boolean certain
714
+ ) {
715
+ numberOfLoadsFromOperandRec ( operandFrom , operandTo , n , certain )
698
716
or
699
717
not Ssa:: isDereference ( _, operandFrom ) and
700
718
not conversionFlow ( operandFrom , _, _, _) and
701
719
operandFrom = operandTo and
702
- n = 0
720
+ n = 0 and
721
+ certain = true
703
722
}
704
723
705
724
// Needed to join on both an operand and an index at the same time.
@@ -729,7 +748,7 @@ predicate readStep(Node node1, Content c, Node node2) {
729
748
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
730
749
// in `storeStep`.
731
750
nodeHasOperand ( node1 , fa1 .getObjectAddressOperand ( ) , 1 ) and
732
- numberOfLoadsFromOperand ( fa1 , operand , numberOfLoads )
751
+ numberOfLoadsFromOperand ( fa1 , operand , numberOfLoads , _ )
733
752
|
734
753
exists ( FieldContent fc | fc = c |
735
754
fc .getField ( ) = fa1 .getField ( ) and
@@ -747,7 +766,33 @@ predicate readStep(Node node1, Content c, Node node2) {
747
766
* Holds if values stored inside content `c` are cleared at node `n`.
748
767
*/
749
768
predicate clearsContent ( Node n , Content c ) {
750
- none ( ) // stub implementation
769
+ n =
770
+ any ( PostUpdateNode pun , Content d | d .impliesClearOf ( c ) and storeStepImpl ( _, d , pun , true ) | pun )
771
+ .getPreUpdateNode ( ) and
772
+ (
773
+ // The crement operations and pointer addition and subtraction self-assign. We do not
774
+ // want to clear the contents if it is indirectly pointed at by any of these operations,
775
+ // as part of the contents might still be accessible afterwards. If there is no such
776
+ // indirection clearing the contents is safe.
777
+ not exists ( Operand op , Cpp:: Operation p |
778
+ n .( IndirectOperand ) .hasOperandAndIndirectionIndex ( op , _) and
779
+ (
780
+ p instanceof Cpp:: AssignPointerAddExpr or
781
+ p instanceof Cpp:: AssignPointerSubExpr or
782
+ p instanceof Cpp:: CrementOperation
783
+ )
784
+ |
785
+ p .getAnOperand ( ) = op .getUse ( ) .getAst ( )
786
+ )
787
+ or
788
+ forex ( PostUpdateNode pun , Content d |
789
+ pragma [ only_bind_into ] ( d ) .impliesClearOf ( pragma [ only_bind_into ] ( c ) ) and
790
+ storeStepImpl ( _, d , pun , true ) and
791
+ pun .getPreUpdateNode ( ) = n
792
+ |
793
+ c .getIndirectionIndex ( ) = d .getIndirectionIndex ( )
794
+ )
795
+ )
751
796
}
752
797
753
798
/**
0 commit comments