@@ -1142,7 +1142,8 @@ private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawI
11421142}
11431143
11441144private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase ,
1145- RawIndirectInstruction {
1145+ RawIndirectInstruction
1146+ {
11461147 IndirectInstructionIndirectExprNode ( ) { indirectExprNodeShouldBeIndirectInstruction ( this , _) }
11471148
11481149 final override Expr getConvertedExpr ( int index ) {
@@ -1612,39 +1613,96 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
16121613cached
16131614private module ExprFlowCached {
16141615 /**
1615- * Holds if `n1.asExpr()` doesn't have a result and `n1` flows to `n2` in a single
1616+ * Holds if `n` is an indirect operand of a `PointerArithmeticInstruction`, and
1617+ * `e` is the result of loading from the `PointerArithmeticInstruction`.
1618+ */
1619+ private predicate isIndirectBaseOfArrayAccess ( IndirectOperand n , Expr e ) {
1620+ exists ( LoadInstruction load , PointerArithmeticInstruction pai |
1621+ pai = load .getSourceAddress ( ) and
1622+ pai .getLeftOperand ( ) = n .getOperand ( ) and
1623+ n .getIndirectionIndex ( ) = 1 and
1624+ e = load .getConvertedResultExpression ( )
1625+ )
1626+ }
1627+
1628+ /**
1629+ * Gets the expression associated with node `n`, if any.
1630+ *
1631+ * Unlike `n.asExpr()`, this predicate will also get the
1632+ * expression `*(x + i)` when `n` is the indirect node
1633+ * for `x`. This ensures that an assignment in a long chain
1634+ * of assignments in a macro expansion is properly mapped
1635+ * to the previous assignment. For example, in:
1636+ * ```cpp
1637+ * *x = source();
1638+ * use(x[0]);
1639+ * use(x[1]);
1640+ * ...
1641+ * use(x[i]);
1642+ * use(x[i+1]);
1643+ * ...
1644+ * use(x[N]);
1645+ * ```
1646+ * To see what the problem would be if `asExpr(n)` was replaced
1647+ * with `n.asExpr()`, consider the transitive closure over
1648+ * `localStepFromNonExpr` in `localStepsToExpr`. We start at `n2`
1649+ * for which `n.asExpr()` exists. For example, `n2` in the above
1650+ * example could be a `x[i]` in any of the `use(x[i])` above.
1651+ *
1652+ * We then step to a dataflow predecessor of `n2`. In the above
1653+ * code fragment, thats the indirect node corresponding to `x` in
1654+ * `x[i-1]`. Since this doesn't have a result for `Node::asExpr()`
1655+ * we continue with the recursion until we reach `*x = source()`
1656+ * which does have a result for `Node::asExpr()`.
1657+ *
1658+ * If `N` is very large this blows up.
1659+ *
1660+ * To fix this, we map the indirect node corresponding to `x` to
1661+ * in `x[i - 1]` to the `x[i - 1]` expression. This ensures that
1662+ * `x[i]` steps to the expression `x[i - 1]` without traversing the
1663+ * entire chain.
1664+ */
1665+ private Expr asExpr ( Node n ) {
1666+ isIndirectBaseOfArrayAccess ( n , result )
1667+ or
1668+ not isIndirectBaseOfArrayAccess ( n , _) and
1669+ result = n .asExpr ( )
1670+ }
1671+
1672+ /**
1673+ * Holds if `asExpr(n1)` doesn't have a result and `n1` flows to `n2` in a single
16161674 * dataflow step.
16171675 */
16181676 private predicate localStepFromNonExpr ( Node n1 , Node n2 ) {
1619- not exists ( n1 . asExpr ( ) ) and
1677+ not exists ( asExpr ( n1 ) ) and
16201678 localFlowStep ( n1 , n2 )
16211679 }
16221680
16231681 /**
1624- * Holds if `n1. asExpr()` doesn't have a result, `n2. asExpr() = e2` and
1625- * `n2` is the first node reachable from `n1` such that `n2. asExpr()` exists.
1682+ * Holds if `asExpr(n1 )` doesn't have a result, `asExpr(n2 ) = e2` and
1683+ * `n2` is the first node reachable from `n1` such that `asExpr(n2 )` exists.
16261684 */
16271685 pragma [ nomagic]
16281686 private predicate localStepsToExpr ( Node n1 , Node n2 , Expr e2 ) {
16291687 localStepFromNonExpr * ( n1 , n2 ) and
1630- e2 = n2 . asExpr ( )
1688+ e2 = asExpr ( n2 )
16311689 }
16321690
16331691 /**
1634- * Holds if `n1. asExpr() = e1` and `n2. asExpr() = e2` and `n2` is the first node
1635- * reachable from `n1` such that `n2. asExpr()` exists.
1692+ * Holds if `asExpr(n1 ) = e1` and `asExpr(n2 ) = e2` and `n2` is the first node
1693+ * reachable from `n1` such that `asExpr(n2 )` exists.
16361694 */
16371695 private predicate localExprFlowSingleExprStep ( Node n1 , Expr e1 , Node n2 , Expr e2 ) {
16381696 exists ( Node mid |
16391697 localFlowStep ( n1 , mid ) and
16401698 localStepsToExpr ( mid , n2 , e2 ) and
1641- e1 = n1 . asExpr ( )
1699+ e1 = asExpr ( n1 )
16421700 )
16431701 }
16441702
16451703 /**
1646- * Holds if `n1. asExpr() = e1` and `e1 != e2` and `n2` is the first reachable node from
1647- * `n1` such that `n2. asExpr() = e2`.
1704+ * Holds if `asExpr(n1 ) = e1` and `e1 != e2` and `n2` is the first reachable node from
1705+ * `n1` such that `asExpr(n2 ) = e2`.
16481706 */
16491707 private predicate localExprFlowStepImpl ( Node n1 , Expr e1 , Node n2 , Expr e2 ) {
16501708 exists ( Node n , Expr e | localExprFlowSingleExprStep ( n1 , e1 , n , e ) |
0 commit comments