Skip to content

Commit 60cef60

Browse files
committed
JS: ensure PropWrites exist for all instance members
1 parent 5815aa1 commit 60cef60

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,29 @@ module DataFlow {
494494
override ControlFlowNode getWriteNode() { result = prop }
495495
}
496496

497+
/**
498+
* An instance method definition, viewed as a data flow node that adds
499+
* a property to an unseen value.
500+
*/
501+
private class InstanceMethodAsPropWrite extends PropWrite, PropNode {
502+
override MethodDefinition prop;
503+
504+
InstanceMethodAsPropWrite() { not prop.isStatic() }
505+
506+
override Node getBase() { none() } // The prototype has no DataFlow node
507+
508+
override Expr getPropertyNameExpr() { result = prop.getNameExpr() }
509+
510+
override string getPropertyName() { result = prop.getName() }
511+
512+
override Node getRhs() {
513+
not prop instanceof AccessorMethodDefinition and
514+
result = valueNode(prop.getInit())
515+
}
516+
517+
override ControlFlowNode getWriteNode() { result = prop }
518+
}
519+
497520
/**
498521
* A JSX attribute definition, viewed as a data flow node that writes properties to
499522
* the JSX element it is in.
@@ -532,14 +555,13 @@ module DataFlow {
532555
}
533556

534557
/**
535-
* An instance field with an initializer expression, seen as a property write.
558+
* An instance field, seen as a property write.
536559
*/
537560
private class InstanceFieldAsPropWrite extends PropWrite, PropNode {
538561
override FieldDefinition prop;
539562

540563
InstanceFieldAsPropWrite() {
541564
not prop.isStatic() and
542-
exists(prop.getInit()) and
543565
not prop instanceof ParameterField
544566
}
545567

javascript/ql/test/library-tests/PropWrite/PropWrite.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
| classes.ts:3:21:3:20 | constructor() {} |
12
| classes.ts:4:3:4:24 | instanc ... foo(); |
3+
| classes.ts:8:3:8:39 | constru ... eld) {} |
24
| classes.ts:8:15:8:35 | public ... erField |
35
| tst.js:3:5:3:8 | x: 4 |
46
| tst.js:4:5:6:5 | func: f ... ;\\n } |
57
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } |
8+
| tst.js:12:9:12:8 | constructor() {} |
69
| tst.js:13:3:15:3 | static ... x);\\n } |
10+
| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } |
711
| tst.js:21:1:21:6 | C.prop |
812
| tst.js:24:13:24:27 | onClick={click} |
913
| tst.js:27:3:27:26 | get x() ... null; } |

javascript/ql/test/library-tests/PropWrite/PropWritePropName.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
| classes.ts:3:21:3:20 | constructor() {} | constructor |
12
| classes.ts:4:3:4:24 | instanc ... foo(); | instanceField |
3+
| classes.ts:8:3:8:39 | constru ... eld) {} | constructor |
24
| classes.ts:8:15:8:35 | public ... erField | parameterField |
35
| tst.js:3:5:3:8 | x: 4 | x |
46
| tst.js:4:5:6:5 | func: f ... ;\\n } | func |
57
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | f |
8+
| tst.js:12:9:12:8 | constructor() {} | constructor |
69
| tst.js:13:3:15:3 | static ... x);\\n } | func |
10+
| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | f |
711
| tst.js:21:1:21:6 | C.prop | prop |
812
| tst.js:24:13:24:27 | onClick={click} | onClick |
913
| tst.js:27:3:27:26 | get x() ... null; } | x |

javascript/ql/test/library-tests/PropWrite/PropWriteRhs.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
| classes.ts:3:21:3:20 | constructor() {} | classes.ts:3:21:3:20 | () {} |
12
| classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:4:19:4:23 | foo() |
3+
| classes.ts:8:3:8:39 | constru ... eld) {} | classes.ts:8:3:8:39 | constru ... eld) {} |
24
| classes.ts:8:15:8:35 | public ... erField | classes.ts:8:22:8:35 | parameterField |
35
| tst.js:3:5:3:8 | x: 4 | tst.js:3:8:3:8 | 4 |
46
| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:4:11:6:5 | functio ... ;\\n } |
57
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:7:6:9:5 | () {\\n ... ;\\n } |
8+
| tst.js:12:9:12:8 | constructor() {} | tst.js:12:9:12:8 | () {} |
69
| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } |
10+
| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | tst.js:16:4:18:3 | (x) {\\n ... x);\\n } |
711
| tst.js:21:1:21:6 | C.prop | tst.js:21:10:21:11 | 56 |
812
| tst.js:24:13:24:27 | onClick={click} | tst.js:24:22:24:26 | click |
913
| tst.js:32:5:32:8 | n: 1 | tst.js:32:8:32:8 | 1 |

0 commit comments

Comments
 (0)