Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 125d146

Browse files
committed
JS: Add DataFlow::functionForwardingStep
1 parent a3421e7 commit 125d146

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,4 +1683,59 @@ module DataFlow {
16831683
import TypeTracking
16841684

16851685
predicate localTaintStep = TaintTracking::localTaintStep/2;
1686+
1687+
/**
1688+
* Holds if the function in `succ` forwards all its arguments to a call to `pred` and returns
1689+
* its result. This can thus be seen as a step `pred -> succ` used for tracking function values
1690+
* through "wrapper functions", since the `succ` function partially replicates behavior of `pred`.
1691+
*
1692+
* Examples:
1693+
* ```js
1694+
* function f(x) {
1695+
* return g(x); // step: g -> f
1696+
* }
1697+
*
1698+
* function doExec(x) {
1699+
* console.log(x);
1700+
* return exec(x); // step: exec -> doExec
1701+
* }
1702+
*
1703+
* function doEither(x, y) {
1704+
* if (x > y) {
1705+
* return foo(x, y); // step: foo -> doEither
1706+
* } else {
1707+
* return bar(x, y); // step: bar -> doEither
1708+
* }
1709+
* }
1710+
*
1711+
* function wrapWithLogging(f) {
1712+
* return (x) => {
1713+
* console.log(x);
1714+
* return f(x); // step: f -> anonymous function
1715+
* }
1716+
* }
1717+
* wrapWithLogging(g); // step: g -> wrapWithLogging(g)
1718+
* ```
1719+
*/
1720+
predicate functionForwardingStep(DataFlow::Node pred, DataFlow::Node succ) {
1721+
exists(DataFlow::FunctionNode function, DataFlow::CallNode call |
1722+
call.flowsTo(function.getReturnNode()) and
1723+
forall(int i | exists([call.getArgument(i), function.getParameter(i)]) |
1724+
function.getParameter(i).flowsTo(call.getArgument(i))
1725+
) and
1726+
pred = call.getCalleeNode() and
1727+
succ = function
1728+
)
1729+
or
1730+
// Given a generic wrapper function like,
1731+
//
1732+
// function wrap(f) { return (x, y) => f(x, y) };
1733+
//
1734+
// add steps through calls to that function: `g -> wrap(g)`
1735+
exists(DataFlow::FunctionNode wrapperFunction, SourceNode param, Node paramUse |
1736+
FlowSteps::argumentPassing(succ, pred, wrapperFunction.getFunction(), param) and
1737+
param.flowsTo(paramUse) and
1738+
functionForwardingStep(paramUse, wrapperFunction.getReturnNode().getALocalSource())
1739+
)
1740+
}
16861741
}

0 commit comments

Comments
 (0)