Skip to content

Commit f05e777

Browse files
author
Max Schaefer
committed
JavaScript: Patch CFG to improve support for non-top level import declarations.
1 parent 18a74a2 commit f05e777

File tree

1 file changed

+45
-1
lines changed
  • javascript/ql/src/semmle/javascript

1 file changed

+45
-1
lines changed

javascript/ql/src/semmle/javascript/CFG.qll

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ import javascript
281281
*/
282282
class ControlFlowNode extends @cfg_node, Locatable {
283283
/** Gets a node succeeding this node in the CFG. */
284-
ControlFlowNode getASuccessor() {
284+
cached ControlFlowNode getASuccessor() {
285285
successor(this, result)
286286
}
287287

@@ -457,3 +457,47 @@ class ConcreteControlFlowNode extends ControlFlowNode {
457457
not this instanceof SyntheticControlFlowNode
458458
}
459459
}
460+
461+
/**
462+
* A CFG node corresponding to a nested (that is, non-toplevel) import declaration.
463+
*
464+
* This is a non-standard language feature that is not currently supported very well
465+
* by the extractor, in particular such imports do not appear in the control flow graph
466+
* generated by the extractor. We patch them in by overriding `getASuccessor`; once an
467+
* extractor fix becomes available, this class can be removed.
468+
*/
469+
private class NestedImportDeclaration extends ImportDeclaration {
470+
NestedImportDeclaration() {
471+
exists (ASTNode p | p = getParent() |
472+
not p instanceof TopLevel
473+
) and
474+
// if there are no specifiers, the default control flow graph is fine
475+
exists(getASpecifier())
476+
}
477+
478+
override ControlFlowNode getASuccessor() {
479+
result = getSpecifier(0).getFirstControlFlowNode()
480+
}
481+
}
482+
483+
/**
484+
* A CFG node corresponding to an import specifier in a nested import declaration.
485+
*
486+
* As for `NestedImportDeclaration` above, this is a temporary workaround that will be
487+
* removed once extractor support for this non-standard language feature becomes available.
488+
*/
489+
private class NestedImportSpecifier extends ImportSpecifier {
490+
NestedImportDeclaration decl;
491+
int i;
492+
493+
NestedImportSpecifier() {
494+
this = decl.getSpecifier(i)
495+
}
496+
497+
override ControlFlowNode getASuccessor() {
498+
result = decl.getSpecifier(i+1).getFirstControlFlowNode()
499+
or
500+
not exists(decl.getSpecifier(i+1)) and
501+
successor(decl, result)
502+
}
503+
}

0 commit comments

Comments
 (0)