Files
codeql/docs/language/ql-training/slide-snippets/global-data-flow-extra-slides.rst
2019-09-05 08:40:36 +01:00

68 lines
2.3 KiB
ReStructuredText

Exercise: How not to do global data flow
========================================
Implement a ``flowStep`` predicate extending ``localFlowStep`` with steps through function calls and returns. Why might we not want to use this?
.. code-block:: ql
predicate stepIn(Call c, DataFlow::Node arg, DataFlow::ParameterNode parm) {
exists(int i | arg.asExpr() = c.getArgument(i) |
parm.asParameter() = c.getTarget().getParameter(i))
}
predicate stepOut(Call c, DataFlow::Node ret, DataFlow::Node res) {
exists(ReturnStmt retStmt | retStmt.getEnclosingFunction() = c.getTarget() |
ret.asExpr() = retStmt.getExpr() and res.asExpr() = c)
}
predicate flowStep(DataFlow::Node pred, DataFlow::Node succ) {
DataFlow::localFlowStep(pred, succ) or
stepIn(_, pred, succ) or
stepOut(_, pred, succ)
}
.. rst-class:: mismatched-calls-and-returns
Mismatched calls and returns
============================
.. diagram copied from google slides
Balancing calls and returns
===========================
- If we simply take ``flowStep*``, we might mismatch calls and returns, causing imprecision, which in turn may cause false positives.
- Instead, make sure that matching ``stepIn``/``stepOut`` pairs talk about the same call site:
.. code-block:: ql
predicate balancedPath(DataFlow::Node src, DataFlow::Node snk) {
src = snk or DataFlow::localFlowStep(src, snk) or
exists(DataFlow::Node m | balancedPath(src, m) | balancedPath(m, snk)) or
exists(Call c, DataFlow::Node parm, DataFlow::Node ret |
stepIn(c, src, parm) and
balancedPath(parm, ret) and
stepOut(c, ret, snk)
)
}
Summary-based global data flow
==============================
- To avoid traversing the same paths many times, we compute function summaries that record if a function parameter flows into a return value:
.. code-block:: ql
predicate returnsParameter(Function f, int i) {
exists (Parameter p, ReturnStmt retStmt, Expr ret |
p = f.getParameter(i) and
retStmt.getEnclosingFunction() = f and
ret = retStmt.getExpr() and
balancedPath(DataFlow::parameterNode(p), DataFlow::exprNode(ret))
)
}
- Use this predicate in ``balancedPath`` instead of ``stepIn``/``stepOut`` pairs.