Skip to content

Commit 9aaea40

Browse files
committed
JS: address comments and support TrackedNode
1 parent 6d1eab8 commit 9aaea40

File tree

4 files changed

+37
-21
lines changed

4 files changed

+37
-21
lines changed

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

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ private predicate storeStep(
607607
summary = PathSummary::level()
608608
or
609609
exists(Function f, DataFlow::Node mid |
610-
// `f` stores its parameter `pred` in property `prop` of a value that it returns,
610+
// `f` stores its parameter `pred` in property `prop` of a value that flows back to the caller,
611611
// and `succ` is an invocation of `f`
612612
reachableFromInput(f, succ, pred, mid, cfg, summary) and
613613
(
@@ -619,21 +619,6 @@ private predicate storeStep(
619619
)
620620
}
621621

622-
/**
623-
* Holds if `f` may return `base`, which has a write of property `prop` with right-hand side `rhs`.
624-
*/
625-
predicate returnedPropWrite(Function f, DataFlow::SourceNode base, string prop, DataFlow::Node rhs) {
626-
base.hasPropertyWrite(prop, rhs) and
627-
base.flowsToExpr(f.getAReturnedExpr())
628-
}
629-
630-
/**
631-
* Holds if `f` may return `base`, which has a write of property `prop` with right-hand side `rhs`.
632-
*/
633-
predicate receiverPropWrite(Function f, string prop, DataFlow::Node rhs) {
634-
DataFlow::thisNode(f).hasPropertyWrite(prop, rhs)
635-
}
636-
637622
/**
638623
* Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable
639624
* from the base of that write under configuration `cfg` (possibly through callees) along a

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,16 @@ private module NodeTracking {
167167
basicStoreStep(pred, succ, prop) and
168168
summary = PathSummary::level()
169169
or
170-
exists(Function f, DataFlow::Node mid, DataFlow::SourceNode base |
171-
// `f` stores its parameter `pred` in property `prop` of a value that it returns,
170+
exists(Function f, DataFlow::Node mid |
171+
// `f` stores its parameter `pred` in property `prop` of a value that flows back to the caller,
172172
// and `succ` is an invocation of `f`
173173
reachableFromInput(f, succ, pred, mid, summary) and
174-
base.hasPropertyWrite(prop, mid) and
175-
base.flowsToExpr(f.getAReturnedExpr())
174+
(
175+
returnedPropWrite(f, _, prop, mid)
176+
or
177+
succ instanceof DataFlow::NewNode and
178+
receiverPropWrite(f, prop, mid)
179+
)
176180
)
177181
}
178182

javascript/ql/src/semmle/javascript/dataflow/internal/FlowSteps.qll

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ predicate callStep(DataFlow::Node pred, DataFlow::Node succ) {
115115

116116
/**
117117
* Holds if there is a flow step from `pred` to `succ` through returning
118-
* from a function call.
118+
* from a function call or the receiver flowing out of a constructor call.
119119
*/
120120
predicate returnStep(DataFlow::Node pred, DataFlow::Node succ) {
121121
exists(Function f | calls(succ, f) |
@@ -266,6 +266,21 @@ predicate callback(DataFlow::Node arg, DataFlow::SourceNode cb) {
266266
)
267267
}
268268

269+
/**
270+
* Holds if `f` may return `base`, which has a write of property `prop` with right-hand side `rhs`.
271+
*/
272+
predicate returnedPropWrite(Function f, DataFlow::SourceNode base, string prop, DataFlow::Node rhs) {
273+
base.hasPropertyWrite(prop, rhs) and
274+
base.flowsToExpr(f.getAReturnedExpr())
275+
}
276+
277+
/**
278+
* Holds if `f` may assign `rhs` to `this.prop`.
279+
*/
280+
predicate receiverPropWrite(Function f, string prop, DataFlow::Node rhs) {
281+
DataFlow::thisNode(f).hasPropertyWrite(prop, rhs)
282+
}
283+
269284
/**
270285
* A utility class that is equivalent to `boolean` but does not require type joining.
271286
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as dummy from 'dummy';
2+
3+
class C {
4+
constructor() {
5+
this.field = new Object();
6+
}
7+
}
8+
9+
function test() {
10+
let x = new C().field;
11+
foo(x);
12+
}

0 commit comments

Comments
 (0)