@@ -1142,7 +1142,8 @@ private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawI
1142
1142
}
1143
1143
1144
1144
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase ,
1145
- RawIndirectInstruction {
1145
+ RawIndirectInstruction
1146
+ {
1146
1147
IndirectInstructionIndirectExprNode ( ) { indirectExprNodeShouldBeIndirectInstruction ( this , _) }
1147
1148
1148
1149
final override Expr getConvertedExpr ( int index ) {
@@ -1612,39 +1613,96 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
1612
1613
cached
1613
1614
private module ExprFlowCached {
1614
1615
/**
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
1616
1674
* dataflow step.
1617
1675
*/
1618
1676
private predicate localStepFromNonExpr ( Node n1 , Node n2 ) {
1619
- not exists ( n1 . asExpr ( ) ) and
1677
+ not exists ( asExpr ( n1 ) ) and
1620
1678
localFlowStep ( n1 , n2 )
1621
1679
}
1622
1680
1623
1681
/**
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.
1626
1684
*/
1627
1685
pragma [ nomagic]
1628
1686
private predicate localStepsToExpr ( Node n1 , Node n2 , Expr e2 ) {
1629
1687
localStepFromNonExpr * ( n1 , n2 ) and
1630
- e2 = n2 . asExpr ( )
1688
+ e2 = asExpr ( n2 )
1631
1689
}
1632
1690
1633
1691
/**
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.
1636
1694
*/
1637
1695
private predicate localExprFlowSingleExprStep ( Node n1 , Expr e1 , Node n2 , Expr e2 ) {
1638
1696
exists ( Node mid |
1639
1697
localFlowStep ( n1 , mid ) and
1640
1698
localStepsToExpr ( mid , n2 , e2 ) and
1641
- e1 = n1 . asExpr ( )
1699
+ e1 = asExpr ( n1 )
1642
1700
)
1643
1701
}
1644
1702
1645
1703
/**
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`.
1648
1706
*/
1649
1707
private predicate localExprFlowStepImpl ( Node n1 , Expr e1 , Node n2 , Expr e2 ) {
1650
1708
exists ( Node n , Expr e | localExprFlowSingleExprStep ( n1 , e1 , n , e ) |
0 commit comments