JS: Recognize field types in untyped code

This commit is contained in:
Asger Feldthaus
2020-09-29 11:08:22 +01:00
parent d38121f54a
commit 3dabff6b17
3 changed files with 34 additions and 4 deletions

View File

@@ -34,6 +34,13 @@ abstract class ExtendCall extends DataFlow::CallNode {
}
}
/** A version of `JQuery::dollarSource()` with fewer dependencies. */
private DataFlow::SourceNode localDollar() {
result.accessesGlobal(["$", "jQuery"])
or
result = DataFlow::moduleImport("jquery")
}
/**
* An extend call of form `extend(true/false, dst, src1, src2, ...)`, where the true/false
* argument is possibly omitted.
@@ -47,9 +54,7 @@ private class ExtendCallWithFlag extends ExtendCall {
name = "node.extend"
)
or
// Match $.extend using the source of `$` only, as ExtendCall should not
// depend on type tracking.
this = JQuery::dollarSource().getAMemberCall("extend")
this = localDollar().getAMemberCall("extend")
}
/**

View File

@@ -228,7 +228,7 @@ module DataFlow {
*
* Doesn't take field types and function return types into account.
*/
private JSDocTypeExpr getFallbackTypeAnnotation() {
private TypeAnnotation getFallbackTypeAnnotation() {
exists(BindingPattern pattern |
this = valueNode(pattern) and
not ast_node_type(pattern, _) and
@@ -236,6 +236,11 @@ module DataFlow {
)
or
result = getAPredecessor().getFallbackTypeAnnotation()
or
exists(DataFlow::ClassNode cls, string fieldName |
this = cls.getAReceiverNode().getAPropertyRead(fieldName) and
result = cls.getFieldTypeAnnotation(fieldName)
)
}
/**

View File

@@ -995,6 +995,13 @@ class ClassNode extends DataFlow::SourceNode {
predicate hasQualifiedName(string name) {
getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name))
}
/**
* Gets the type annotation for the field `fieldName`, if any.
*/
TypeAnnotation getFieldTypeAnnotation(string fieldName) {
result = impl.getFieldTypeAnnotation(fieldName)
}
}
module ClassNode {
@@ -1047,6 +1054,11 @@ module ClassNode {
* of this node.
*/
abstract DataFlow::Node getASuperClassNode();
/**
* Gets the type annotation for the field `fieldName`, if any.
*/
TypeAnnotation getFieldTypeAnnotation(string fieldName) { none() }
}
/**
@@ -1106,6 +1118,14 @@ module ClassNode {
}
override DataFlow::Node getASuperClassNode() { result = astNode.getSuperClass().flow() }
override TypeAnnotation getFieldTypeAnnotation(string fieldName) {
exists(FieldDeclaration field |
field.getDeclaringClass() = astNode and
fieldName = field.getName() and
result = field.getTypeAnnotation()
)
}
}
private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) {