Merge pull request #945 from asger-semmle/extensible-module-import

Approved by xiemaisi
This commit is contained in:
semmle-qlci
2019-02-26 09:26:28 +00:00
committed by GitHub
4 changed files with 86 additions and 43 deletions

View File

@@ -403,57 +403,83 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode {
*
* For compatibility with old transpilers, we treat `import * from '...'`
* as a default import as well.
*
* Additional import nodes can be added by subclassing `ModuleImportNode::Range`.
*/
class ModuleImportNode extends DataFlow::SourceNode {
string path;
ModuleImportNode::Range range;
ModuleImportNode() {
// `require("http")`
exists(Require req | req.getImportedPath().getValue() = path | this = DataFlow::valueNode(req))
or
// `import http = require("http")`
exists(ExternalModuleReference req | req.getImportedPath().getValue() = path |
this = DataFlow::valueNode(req)
)
or
// `import * as http from 'http'` or `import http from `http`'
exists(ImportDeclaration id, ImportSpecifier is, SsaExplicitDefinition ssa |
id.getImportedPath().getValue() = path and
is = id.getASpecifier() and
ssa.getDef() = is and
this = DataFlow::ssaDefinitionNode(ssa)
|
is instanceof ImportNamespaceSpecifier and
count(id.getASpecifier()) = 1
or
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))
)
or
// AMD require
exists(AMDModuleDefinition amd, CallExpr req |
req = amd.getARequireCall() and
this = DataFlow::valueNode(req) and
path = req.getArgument(0).(ConstantString).getStringValue()
)
}
ModuleImportNode() { this = range }
/** Gets the path of the imported module. */
string getPath() { result = path }
string getPath() { result = range.getPath() }
}
module ModuleImportNode {
/**
* A data flow node that refers to an imported module.
*/
abstract class Range extends DataFlow::SourceNode {
/** Gets the path of the imported module. */
abstract string getPath();
}
private class DefaultRange extends Range {
string path;
DefaultRange() {
// `require("http")`
exists(Require req | req.getImportedPath().getValue() = path |
this = DataFlow::valueNode(req)
)
or
// `import http = require("http")`
exists(ExternalModuleReference req | req.getImportedPath().getValue() = path |
this = DataFlow::valueNode(req)
)
or
// `import * as http from 'http'` or `import http from `http`'
exists(ImportDeclaration id, ImportSpecifier is, SsaExplicitDefinition ssa |
id.getImportedPath().getValue() = path and
is = id.getASpecifier() and
ssa.getDef() = is and
this = DataFlow::ssaDefinitionNode(ssa)
|
is instanceof ImportNamespaceSpecifier and
count(id.getASpecifier()) = 1
or
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))
)
or
// AMD require
exists(AMDModuleDefinition amd, CallExpr req |
req = amd.getARequireCall() and
this = DataFlow::valueNode(req) and
path = req.getArgument(0).(ConstantString).getStringValue()
)
}
/** Gets the path of the imported module. */
override string getPath() { result = path }
}
}
/**
* Gets a (default) import of the module with the given path.
* Gets a (default) import of the module with the given path, such as `require("fs")`
* or `import * as fs from "fs"`.
*
* This predicate can be extended by subclassing `ModuleImportNode::Range`.
*/
ModuleImportNode moduleImport(string path) { result.getPath() = path }

View File

@@ -0,0 +1 @@
| fs | fs | customImport.js:1:12:1:29 | customImport("fs") |

View File

@@ -0,0 +1,15 @@
import javascript
class CustomImport extends DataFlow::ModuleImportNode::Range, DataFlow::CallNode {
CustomImport() {
getCalleeName() = "customImport"
}
override string getPath() {
result = getArgument(0).getStringValue()
}
}
from string path, CustomImport imprt
where imprt = DataFlow::moduleImport(path)
select path, imprt.getPath(), imprt

View File

@@ -0,0 +1 @@
const fs = customImport("fs");