Merge pull request #934 from asger-semmle/module-import

Approved by xiemaisi
This commit is contained in:
semmle-qlci
2019-02-25 09:46:52 +00:00
committed by GitHub
15 changed files with 119 additions and 8 deletions

View File

@@ -37,6 +37,9 @@ module DataFlow {
TThisNode(StmtContainer f) { f.(Function).getThisBinder() = f or f instanceof TopLevel } or
TUnusedParameterNode(SimpleParameter p) {
not exists(SsaExplicitDefinition ssa | p = ssa.getDef())
} or
TDestructuredModuleImportNode(ImportDeclaration decl) {
exists(decl.getASpecifier().getImportedName())
}
/**
@@ -351,6 +354,25 @@ module DataFlow {
override string toString() { result = "reflective call" }
}
/**
* A node referring to the module imported at a named or default ES2015 import declaration.
*/
private class DestructuredModuleImportNode extends Node, TDestructuredModuleImportNode {
ImportDeclaration imprt;
DestructuredModuleImportNode() { this = TDestructuredModuleImportNode(imprt) }
override BasicBlock getBasicBlock() { result = imprt.getBasicBlock() }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
imprt.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override string toString() { result = imprt.toString() }
}
/**
* A data flow node that reads or writes an object property or class member.
*
@@ -668,6 +690,30 @@ module DataFlow {
override string getPropertyName() { none() }
}
/**
* A named import specifier seen as a property read on the imported module.
*/
private class ImportSpecifierAsPropRead extends PropRead {
ImportDeclaration imprt;
ImportSpecifier spec;
ImportSpecifierAsPropRead() {
spec = imprt.getASpecifier() and
exists(spec.getImportedName()) and
exists(SsaExplicitDefinition ssa |
ssa.getDef() = spec and
this = TSsaDefNode(ssa)
)
}
override Node getBase() { result = TDestructuredModuleImportNode(imprt) }
override Expr getPropertyNameExpr() { result = spec.getImported() }
override string getPropertyName() { result = spec.getImportedName() }
}
/**
* A data flow node representing an unused parameter.
*
@@ -886,6 +932,16 @@ module DataFlow {
*/
DataFlow::ThisNode thisNode(StmtContainer container) { result = TThisNode(container) }
/**
* INTERNAL. DO NOT USE.
*
* Gets the data flow node holding the reference to the module being destructured at
* the given import declaration.
*/
DataFlow::Node destructuredModuleImportNode(ImportDeclaration imprt) {
result = TDestructuredModuleImportNode(imprt)
}
/**
* A classification of flows that are not modeled, or only modeled incompletely, by
* `DataFlowNode`:

View File

@@ -429,6 +429,12 @@ class ModuleImportNode extends DataFlow::SourceNode {
is.getImportedName() = "default"
)
or
// `import { createServer } from 'http'`
exists(ImportDeclaration id |
this = DataFlow::destructuredModuleImportNode(id) and
id.getImportedPath().getValue() = path
)
or
// declared AMD dependency
exists(AMDModuleDefinition amd |
this = DataFlow::parameterNode(amd.getDependencyParameter(path))
@@ -458,14 +464,6 @@ ModuleImportNode moduleImport(string path) { result.getPath() = path }
*/
DataFlow::SourceNode moduleMember(string path, string m) {
result = moduleImport(path).getAPropertyRead(m)
or
exists(ImportDeclaration id, ImportSpecifier is, SsaExplicitDefinition ssa |
id.getImportedPath().getValue() = path and
is = id.getASpecifier() and
is.getImportedName() = m and
ssa.getDef() = is and
result = DataFlow::ssaDefinitionNode(ssa)
)
}
/**

View File

@@ -207,6 +207,8 @@ module SourceNode {
this instanceof DataFlow::Impl::InvokeNodeDef
or
DataFlow::thisNode(this, _)
or
this = DataFlow::destructuredModuleImportNode(_)
}
}
}

View File

@@ -175,6 +175,25 @@ private class AnalyzedNamespaceImport extends AnalyzedImport {
}
}
/**
* Flow analysis for namespace imports.
*/
private class AnalyzedDestructuredImport extends AnalyzedPropertyRead {
Module imported;
AnalyzedDestructuredImport() {
exists(ImportDeclaration id |
this = DataFlow::destructuredModuleImportNode(id) and
imported = id.getImportedModule()
)
}
override predicate reads(AbstractValue base, string propName) {
base = TAbstractModuleObject(imported) and
propName = "exports"
}
}
/**
* Flow analysis for `require` calls, interpreted as an implicit read of
* the `module.exports` property of the imported module.