JavaScript: Track flow into method receivers.

This commit is contained in:
Max Schaefer
2019-06-25 21:05:32 -07:00
parent b3e8103dce
commit b5b89c0eac
7 changed files with 35 additions and 11 deletions

View File

@@ -795,7 +795,7 @@ private predicate summarizedHigherOrderCall(
) {
exists(
Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner, int j,
DataFlow::Node innerArg, DataFlow::ParameterNode cbParm, PathSummary oldSummary
DataFlow::Node innerArg, DataFlow::SourceNode cbParm, PathSummary oldSummary
|
reachableFromInput(f, outer, arg, innerArg, cfg, oldSummary) and
argumentPassing(outer, cb, f, cbParm) and

View File

@@ -215,7 +215,7 @@ private module NodeTracking {
basicLoadStep(pred, succ, prop) and
summary = PathSummary::level()
or
exists (Function f, DataFlow::ParameterNode parm |
exists (Function f, DataFlow::SourceNode parm |
argumentPassing(succ, pred, f, parm) and
reachesReturn(f, parm.getAPropertyRead(prop), summary)
)
@@ -263,7 +263,7 @@ private module NodeTracking {
) {
exists(
Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner, int j,
DataFlow::Node innerArg, DataFlow::ParameterNode cbParm, PathSummary oldSummary
DataFlow::Node innerArg, DataFlow::SourceNode cbParm, PathSummary oldSummary
|
reachableFromInput(f, outer, arg, innerArg, oldSummary) and
argumentPassing(outer, cb, f, cbParm) and

View File

@@ -125,20 +125,27 @@ private module CachedSteps {
*/
cached
predicate argumentPassing(
DataFlow::InvokeNode invk, DataFlow::ValueNode arg, Function f, DataFlow::ParameterNode parm
DataFlow::InvokeNode invk, DataFlow::ValueNode arg, Function f, DataFlow::SourceNode parm
) {
calls(invk, f) and
exists(int i |
f.getParameter(i) = parm.getParameter() and
not parm.isRestParameter() and
arg = invk.getArgument(i)
(
exists(int i, Parameter p |
f.getParameter(i) = p and
not p.isRestParameter() and
arg = invk.getArgument(i) and
parm = DataFlow::parameterNode(p)
)
or
arg = invk.(DataFlow::MethodCallNode).getReceiver() and
parm = DataFlow::thisNode(f)
)
or
exists(DataFlow::Node callback, int i |
exists(DataFlow::Node callback, int i, Parameter p |
invk.(DataFlow::AdditionalPartialInvokeNode).isPartialArgument(callback, arg, i) and
partiallyCalls(invk, callback, f) and
parm.getParameter() = f.getParameter(i) and
not parm.isRestParameter()
f.getParameter(i) = p and
not p.isRestParameter() and
parm = DataFlow::parameterNode(p)
)
}

View File

@@ -38,6 +38,7 @@
| tst2.js:3:17:3:26 | "tainted2" | tst2.js:11:15:11:24 | g(source2) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:10:15:10:24 | g(source1) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:11:15:11:24 | g(source2) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst.js:2:17:2:22 | "src1" | tst.js:39:17:39:17 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:41:19:41:19 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:45:17:45:17 | x |

View File

@@ -39,6 +39,7 @@
| tst2.js:3:17:3:26 | "tainted2" | tst2.js:11:15:11:24 | g(source2) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:10:15:10:24 | g(source1) |
| tst2.js:6:24:6:37 | "also tainted" | tst2.js:11:15:11:24 | g(source2) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst.js:2:17:2:22 | "src1" | tst.js:39:17:39:17 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:41:19:41:19 | x |
| tst.js:2:17:2:22 | "src1" | tst.js:45:17:45:17 | x |

View File

@@ -48,6 +48,7 @@
| tst4.js:2:16:2:24 | "tainted" | tst4.js:15:15:15:31 | id(still_tainted) |
| tst4.js:2:16:2:24 | "tainted" | tst4.js:16:15:16:28 | p.also_tainted |
| tst4.js:2:16:2:24 | "tainted" | tst4.js:17:15:17:28 | substr(source) |
| tst6.mjs:12:14:12:21 | "source" | tst6.mjs:14:12:14:16 | a.m() |
| tst.js:2:17:2:22 | "src1" | tst.js:3:15:3:29 | String(source1) |
| tst.js:2:17:2:22 | "src1" | tst.js:4:15:4:29 | RegExp(source1) |
| tst.js:2:17:2:22 | "src1" | tst.js:5:15:5:33 | new String(source1) |

View File

@@ -0,0 +1,14 @@
class A {
constructor(f) {
this._f = f;
}
m() {
return this._f;
}
}
var source = "source";
var a = new A(source);
var sink = a.m();