Merge pull request #275 from xiemaisi/js/workaround-for-nested-imports

Approved by asger-semmle
This commit is contained in:
semmle-qlci
2018-10-04 08:25:52 +01:00
committed by GitHub
8 changed files with 74 additions and 5 deletions

View File

@@ -281,7 +281,7 @@ import javascript
*/
class ControlFlowNode extends @cfg_node, Locatable {
/** Gets a node succeeding this node in the CFG. */
ControlFlowNode getASuccessor() {
cached ControlFlowNode getASuccessor() {
successor(this, result)
}
@@ -457,3 +457,47 @@ class ConcreteControlFlowNode extends ControlFlowNode {
not this instanceof SyntheticControlFlowNode
}
}
/**
* A CFG node corresponding to a nested (that is, non-toplevel) import declaration.
*
* This is a non-standard language feature that is not currently supported very well
* by the extractor, in particular such imports do not appear in the control flow graph
* generated by the extractor. We patch them in by overriding `getASuccessor`; once an
* extractor fix becomes available, this class can be removed.
*/
private class NestedImportDeclaration extends ImportDeclaration {
NestedImportDeclaration() {
exists (ASTNode p | p = getParent() |
not p instanceof TopLevel
) and
// if there are no specifiers, the default control flow graph is fine
exists(getASpecifier())
}
override ControlFlowNode getASuccessor() {
result = getSpecifier(0).getFirstControlFlowNode()
}
}
/**
* A CFG node corresponding to an import specifier in a nested import declaration.
*
* As for `NestedImportDeclaration` above, this is a temporary workaround that will be
* removed once extractor support for this non-standard language feature becomes available.
*/
private class NestedImportSpecifier extends ImportSpecifier {
NestedImportDeclaration decl;
int i;
NestedImportSpecifier() {
this = decl.getSpecifier(i)
}
override ControlFlowNode getASuccessor() {
result = decl.getSpecifier(i+1).getFirstControlFlowNode()
or
not exists(decl.getSpecifier(i+1)) and
successor(decl, result)
}
}

View File

@@ -27,7 +27,7 @@ class ES2015Module extends Module {
/** Gets an export declaration in this module. */
ExportDeclaration getAnExport() {
result.getContainer() = this
result.getTopLevel() = this
}
override Module getAnImportedModule() {
@@ -55,7 +55,7 @@ class ES2015Module extends Module {
/** An import declaration. */
class ImportDeclaration extends Stmt, Import, @importdeclaration {
override ES2015Module getEnclosingModule() {
result = getContainer()
result = getTopLevel()
}
override PathExprInModule getImportedPath() {
@@ -254,7 +254,7 @@ class BulkReExportDeclaration extends ReExportDeclaration, @exportalldeclaration
* but we ignore this subtlety.
*/
private predicate isShadowedFromBulkExport(BulkReExportDeclaration reExport, string name) {
exists (ExportNamedDeclaration other | other.getContainer() = reExport.getEnclosingModule() |
exists (ExportNamedDeclaration other | other.getTopLevel() = reExport.getEnclosingModule() |
other.getAnExportedDecl().getName() = name
or
other.getASpecifier().getExportedName() = name)

View File

@@ -301,7 +301,7 @@ private class AnalyzedExportAssign extends AnalyzedPropertyWrite, DataFlow::Valu
}
override predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
baseVal = TAbstractModuleObject(exportAssign.getContainer()) and
baseVal = TAbstractModuleObject(exportAssign.getTopLevel()) and
propName = "exports" and
source = this
}