зеркало из https://github.com/github/codeql.git
JS: introduce DataFlow::ClassNode
This commit is contained in:
Родитель
4398670ecc
Коммит
5b7675d972
|
@ -465,3 +465,138 @@ DataFlow::SourceNode moduleMember(string path, string m) {
|
|||
result = DataFlow::ssaDefinitionNode(ssa)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node corresponding to a class definition or a function definition
|
||||
* acting as a class.
|
||||
*
|
||||
* The following patterns are recognized as classes and methods:
|
||||
* ```
|
||||
* class C {
|
||||
* method()
|
||||
* }
|
||||
*
|
||||
* function F() {}
|
||||
*
|
||||
* F.prototype.method = function() {}
|
||||
*
|
||||
* F.prototype = {
|
||||
* method: function() {}
|
||||
* }
|
||||
*
|
||||
* extend(F.prototype, {
|
||||
* method: function() {}
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
class ClassNode extends DataFlow::SourceNode, DataFlow::ValueNode {
|
||||
ClassNode() {
|
||||
astNode instanceof ClassDefinition
|
||||
or
|
||||
astNode instanceof Function and
|
||||
exists(getAPropertyReference("prototype"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the class, if it has one.
|
||||
*/
|
||||
string getName() {
|
||||
result = astNode.(ClassDefinition).getName()
|
||||
or
|
||||
result = astNode.(Function).getName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of the class.
|
||||
*/
|
||||
string describe() {
|
||||
result = astNode.(ClassDefinition).describe()
|
||||
or
|
||||
result = astNode.(Function).describe()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the constructor function of this class.
|
||||
*/
|
||||
FunctionNode getConstructor() {
|
||||
result = astNode.(ClassDefinition).getConstructor().getBody().flow()
|
||||
or
|
||||
result = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance method with the given name, if any.
|
||||
*/
|
||||
FunctionNode getInstanceMethod(string name) {
|
||||
exists(MethodDeclaration method |
|
||||
method = astNode.(ClassDefinition).getMethod(name) and
|
||||
not method.isStatic() and
|
||||
not method.isAmbient() and
|
||||
not method instanceof ConstructorDeclaration and
|
||||
result = method.getBody().flow()
|
||||
)
|
||||
or
|
||||
result = getAPrototypeReference().getAPropertyWrite(name).getRhs().getALocalSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance method of this class.
|
||||
*
|
||||
* The constructor is not considered an instance method.
|
||||
*/
|
||||
FunctionNode getAnInstanceMethod() {
|
||||
exists(MethodDeclaration method |
|
||||
method = astNode.(ClassDefinition).getAMethod() and
|
||||
not method.isStatic() and
|
||||
not method.isAmbient() and
|
||||
not method instanceof ConstructorDeclaration and
|
||||
result = method.getBody().flow()
|
||||
)
|
||||
or
|
||||
result = getAPrototypeReference().getAPropertyWrite().getRhs().getALocalSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the static method of this class with the given name.
|
||||
*/
|
||||
FunctionNode getStaticMethod(string name) {
|
||||
exists(MethodDeclaration method |
|
||||
method = astNode.(ClassDefinition).getMethod(name) and
|
||||
method.isStatic() and
|
||||
not method.isAmbient() and
|
||||
result = method.getBody().flow()
|
||||
)
|
||||
or
|
||||
result = getAPropertyWrite(name).getRhs().getALocalSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a static method of this class.
|
||||
*
|
||||
* The constructor is not considered a static method.
|
||||
*/
|
||||
FunctionNode getAStaticMethod() {
|
||||
exists(MethodDeclaration method |
|
||||
method = astNode.(ClassDefinition).getAMethod() and
|
||||
method.isStatic() and
|
||||
not method.isAmbient() and
|
||||
result = method.getBody().flow()
|
||||
)
|
||||
or
|
||||
result = getAPropertyWrite().getRhs().getALocalSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the prototype of this class.
|
||||
*/
|
||||
private DataFlow::SourceNode getAPrototypeReference() {
|
||||
result = getAPropertyRead("prototype")
|
||||
or
|
||||
result = getAPropertySource("prototype")
|
||||
or
|
||||
exists(ExtendCall call |
|
||||
call.getDestinationOperand() = getAPropertyRead("prototype") and
|
||||
result = call.getASourceOperand()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
| fields.js:1:1:4:1 | class C ... = 42\\n} | fields.js:1:9:1:8 | () {} |
|
||||
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | points.js:2:14:5:3 | (x, y) ... y;\\n } |
|
||||
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | points.js:21:14:24:3 | (x, y, ... c;\\n } |
|
||||
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | staticConstructor.js:1:15:1:14 | () {} |
|
||||
| tst.js:1:9:4:1 | class { ... */ }\\n} | tst.js:2:16:2:50 | () { /* ... r. */ } |
|
||||
| tst.js:6:1:8:1 | class B ... t); }\\n} | tst.js:7:14:7:38 | () { su ... get); } |
|
||||
| tst.js:11:1:14:1 | class C ... () {}\\n} | tst.js:11:9:11:8 | () {} |
|
|
@ -0,0 +1,4 @@
|
|||
import javascript
|
||||
|
||||
from DataFlow::ClassNode class_
|
||||
select class_, class_.getConstructor()
|
|
@ -0,0 +1,5 @@
|
|||
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | dist | points.js:7:11:9:3 | () {\\n ... y);\\n } |
|
||||
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | toString | points.js:11:11:13:3 | () {\\n ... )";\\n } |
|
||||
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | toString | points.js:26:11:28:3 | () {\\n ... ur;\\n } |
|
||||
| tst.js:1:9:4:1 | class { ... */ }\\n} | constructor | tst.js:3:18:3:56 | () { /* ... r. */ } |
|
||||
| tst.js:11:1:14:1 | class C ... () {}\\n} | m | tst.js:12:4:12:8 | () {} |
|
|
@ -0,0 +1,4 @@
|
|||
import javascript
|
||||
|
||||
from DataFlow::ClassNode class_, string name
|
||||
select class_, name, class_.getInstanceMethod(name)
|
|
@ -0,0 +1,3 @@
|
|||
| points.js:1:1:18:1 | class P ... ;\\n }\\n} | className | points.js:15:19:17:3 | () {\\n ... t";\\n } |
|
||||
| points.js:20:1:33:1 | class C ... ;\\n }\\n} | className | points.js:30:19:32:3 | () {\\n ... t";\\n } |
|
||||
| staticConstructor.js:1:1:3:1 | class M ... r"; }\\n} | constructor | staticConstructor.js:2:21:2:59 | () { re ... tor"; } |
|
|
@ -0,0 +1,4 @@
|
|||
import javascript
|
||||
|
||||
from DataFlow::ClassNode class_, string name
|
||||
select class_, name, class_.getStaticMethod(name)
|
Загрузка…
Ссылка в новой задаче