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

Skip to content

Commit 5b7675d

Browse files
committed
JS: introduce DataFlow::ClassNode
1 parent 4398670 commit 5b7675d

7 files changed

Lines changed: 162 additions & 0 deletions

File tree

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

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,3 +465,138 @@ DataFlow::SourceNode moduleMember(string path, string m) {
465465
result = DataFlow::ssaDefinitionNode(ssa)
466466
)
467467
}
468+
469+
/**
470+
* A data flow node corresponding to a class definition or a function definition
471+
* acting as a class.
472+
*
473+
* The following patterns are recognized as classes and methods:
474+
* ```
475+
* class C {
476+
* method()
477+
* }
478+
*
479+
* function F() {}
480+
*
481+
* F.prototype.method = function() {}
482+
*
483+
* F.prototype = {
484+
* method: function() {}
485+
* }
486+
*
487+
* extend(F.prototype, {
488+
* method: function() {}
489+
* });
490+
* ```
491+
*/
492+
class ClassNode extends DataFlow::SourceNode, DataFlow::ValueNode {
493+
ClassNode() {
494+
astNode instanceof ClassDefinition
495+
or
496+
astNode instanceof Function and
497+
exists(getAPropertyReference("prototype"))
498+
}
499+
500+
/**
501+
* Gets the name of the class, if it has one.
502+
*/
503+
string getName() {
504+
result = astNode.(ClassDefinition).getName()
505+
or
506+
result = astNode.(Function).getName()
507+
}
508+
509+
/**
510+
* Gets a description of the class.
511+
*/
512+
string describe() {
513+
result = astNode.(ClassDefinition).describe()
514+
or
515+
result = astNode.(Function).describe()
516+
}
517+
518+
/**
519+
* Gets the constructor function of this class.
520+
*/
521+
FunctionNode getConstructor() {
522+
result = astNode.(ClassDefinition).getConstructor().getBody().flow()
523+
or
524+
result = this
525+
}
526+
527+
/**
528+
* Gets an instance method with the given name, if any.
529+
*/
530+
FunctionNode getInstanceMethod(string name) {
531+
exists(MethodDeclaration method |
532+
method = astNode.(ClassDefinition).getMethod(name) and
533+
not method.isStatic() and
534+
not method.isAmbient() and
535+
not method instanceof ConstructorDeclaration and
536+
result = method.getBody().flow()
537+
)
538+
or
539+
result = getAPrototypeReference().getAPropertyWrite(name).getRhs().getALocalSource()
540+
}
541+
542+
/**
543+
* Gets an instance method of this class.
544+
*
545+
* The constructor is not considered an instance method.
546+
*/
547+
FunctionNode getAnInstanceMethod() {
548+
exists(MethodDeclaration method |
549+
method = astNode.(ClassDefinition).getAMethod() and
550+
not method.isStatic() and
551+
not method.isAmbient() and
552+
not method instanceof ConstructorDeclaration and
553+
result = method.getBody().flow()
554+
)
555+
or
556+
result = getAPrototypeReference().getAPropertyWrite().getRhs().getALocalSource()
557+
}
558+
559+
/**
560+
* Gets the static method of this class with the given name.
561+
*/
562+
FunctionNode getStaticMethod(string name) {
563+
exists(MethodDeclaration method |
564+
method = astNode.(ClassDefinition).getMethod(name) and
565+
method.isStatic() and
566+
not method.isAmbient() and
567+
result = method.getBody().flow()
568+
)
569+
or
570+
result = getAPropertyWrite(name).getRhs().getALocalSource()
571+
}
572+
573+
/**
574+
* Gets a static method of this class.
575+
*
576+
* The constructor is not considered a static method.
577+
*/
578+
FunctionNode getAStaticMethod() {
579+
exists(MethodDeclaration method |
580+
method = astNode.(ClassDefinition).getAMethod() and
581+
method.isStatic() and
582+
not method.isAmbient() and
583+
result = method.getBody().flow()
584+
)
585+
or
586+
result = getAPropertyWrite().getRhs().getALocalSource()
587+
}
588+
589+
/**
590+
* Gets a reference to the prototype of this class.
591+
*/
592+
private DataFlow::SourceNode getAPrototypeReference() {
593+
result = getAPropertyRead("prototype")
594+
or
595+
result = getAPropertySource("prototype")
596+
or
597+
exists(ExtendCall call |
598+
call.getDestinationOperand() = getAPropertyRead("prototype") and
599+
result = call.getASourceOperand()
600+
)
601+
}
602+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| fields.js:1:1:4:1 | class C ... = 42\\n} | fields.js:1:9:1:8 | () {} |
2+
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | points.js:2:14:5:3 | (x, y) ... y;\\n } |
3+
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:21:14:24:3 | (x, y, ... c;\\n } |
4+
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | staticConstructor.js:1:15:1:14 | () {} |
5+
| tst.js:1:9:4:1 | class { ... */ }\\n} | tst.js:2:16:2:50 | () { /* ... r. */ } |
6+
| tst.js:6:1:8:1 | class B ... t); }\\n} | tst.js:7:14:7:38 | () { su ... get); } |
7+
| tst.js:11:1:14:1 | class C ... () {}\\n} | tst.js:11:9:11:8 | () {} |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from DataFlow::ClassNode class_
4+
select class_, class_.getConstructor()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | dist | points.js:7:11:9:3 | () {\\n ... y);\\n } |
2+
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | toString | points.js:11:11:13:3 | () {\\n ... )";\\n } |
3+
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | toString | points.js:26:11:28:3 | () {\\n ... ur;\\n } |
4+
| tst.js:1:9:4:1 | class { ... */ }\\n} | constructor | tst.js:3:18:3:56 | () { /* ... r. */ } |
5+
| tst.js:11:1:14:1 | class C ... () {}\\n} | m | tst.js:12:4:12:8 | () {} |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from DataFlow::ClassNode class_, string name
4+
select class_, name, class_.getInstanceMethod(name)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | className | points.js:15:19:17:3 | () {\\n ... t";\\n } |
2+
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | className | points.js:30:19:32:3 | () {\\n ... t";\\n } |
3+
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | constructor | staticConstructor.js:2:21:2:59 | () { re ... tor"; } |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from DataFlow::ClassNode class_, string name
4+
select class_, name, class_.getStaticMethod(name)

0 commit comments

Comments
 (0)