@@ -651,13 +651,16 @@ predicate jumpStep(Node n1, Node n2) {
651651 * Holds if data can flow from `node1` to `node2` via an assignment to `f`.
652652 * Thus, `node2` references an object with a field `f` that contains the
653653 * value of `node1`.
654+ *
655+ * The boolean `certain` is true if the destination address does not involve
656+ * any pointer arithmetic, and false otherwise.
654657 */
655- predicate storeStep ( Node node1 , Content c , PostFieldUpdateNode node2 ) {
658+ predicate storeStepImpl ( Node node1 , Content c , PostFieldUpdateNode node2 , boolean certain ) {
656659 exists ( int indirectionIndex1 , int numberOfLoads , StoreInstruction store |
657660 nodeHasInstruction ( node1 , store , pragma [ only_bind_into ] ( indirectionIndex1 ) ) and
658661 node2 .getIndirectionIndex ( ) = 1 and
659662 numberOfLoadsFromOperand ( node2 .getFieldAddress ( ) , store .getDestinationAddressOperand ( ) ,
660- numberOfLoads )
663+ numberOfLoads , certain )
661664 |
662665 exists ( FieldContent fc | fc = c |
663666 fc .getField ( ) = node2 .getUpdatedField ( ) and
@@ -671,35 +674,51 @@ predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
671674 )
672675}
673676
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+
674686/**
675687 * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
676688 * operations and exactly `n` `LoadInstruction` operations.
677689 */
678- private predicate numberOfLoadsFromOperandRec ( Operand operandFrom , Operand operandTo , int ind ) {
690+ private predicate numberOfLoadsFromOperandRec (
691+ Operand operandFrom , Operand operandTo , int ind , boolean certain
692+ ) {
679693 exists ( Instruction load | Ssa:: isDereference ( load , operandFrom ) |
680- operandTo = operandFrom and ind = 0
694+ operandTo = operandFrom and ind = 0 and certain = true
681695 or
682- numberOfLoadsFromOperand ( load .getAUse ( ) , operandTo , ind - 1 )
696+ numberOfLoadsFromOperand ( load .getAUse ( ) , operandTo , ind - 1 , certain )
683697 )
684698 or
685- exists ( Operand op , Instruction instr |
699+ exists ( Operand op , Instruction instr , boolean isPointerArith , boolean certain0 |
686700 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
689705 )
690706}
691707
692708/**
693709 * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
694710 * operations and exactly `n` `LoadInstruction` operations.
695711 */
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 )
698716 or
699717 not Ssa:: isDereference ( _, operandFrom ) and
700718 not conversionFlow ( operandFrom , _, _, _) and
701719 operandFrom = operandTo and
702- n = 0
720+ n = 0 and
721+ certain = true
703722}
704723
705724// 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) {
729748 // The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
730749 // in `storeStep`.
731750 nodeHasOperand ( node1 , fa1 .getObjectAddressOperand ( ) , 1 ) and
732- numberOfLoadsFromOperand ( fa1 , operand , numberOfLoads )
751+ numberOfLoadsFromOperand ( fa1 , operand , numberOfLoads , _ )
733752 |
734753 exists ( FieldContent fc | fc = c |
735754 fc .getField ( ) = fa1 .getField ( ) and
@@ -747,7 +766,33 @@ predicate readStep(Node node1, Content c, Node node2) {
747766 * Holds if values stored inside content `c` are cleared at node `n`.
748767 */
749768predicate 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+ )
751796}
752797
753798/**
0 commit comments