Skip to content

Commit e13a9c9

Browse files
committed
JS: Avoid recursion through SourceNode::Range, again
1 parent de879c0 commit e13a9c9

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

javascript/ql/src/semmle/javascript/NodeJS.qll

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,34 @@ private class RequireVariable extends Variable {
202202
*/
203203
private predicate moduleInFile(Module m, File f) { m.getFile() = f }
204204

205+
private predicate isModuleModule(DataFlow::Node nd) {
206+
exists(ImportDeclaration imp |
207+
imp.getImportedPath().getValue() = "module" and
208+
nd = [
209+
DataFlow::destructuredModuleImportNode(imp),
210+
DataFlow::valueNode(imp.getASpecifier().(ImportNamespaceSpecifier))
211+
]
212+
)
213+
or
214+
isModuleModule(nd.getAPredecessor())
215+
}
216+
217+
private predicate isCreateRequire(DataFlow::Node nd) {
218+
exists(PropAccess prop |
219+
isModuleModule(prop.getBase().flow()) and
220+
prop.getPropertyName() = "createRequire" and
221+
nd = prop.flow()
222+
)
223+
or
224+
exists(PropertyPattern prop |
225+
isModuleModule(prop.getObjectPattern().flow()) and
226+
prop.getName() = "createRequire" and
227+
nd = prop.getValuePattern().flow()
228+
)
229+
or
230+
isCreateRequire(nd.getAPredecessor())
231+
}
232+
205233
/**
206234
* Holds if `nd` may refer to `require`, either directly or modulo local data flow.
207235
*/
@@ -215,16 +243,11 @@ private predicate isRequire(DataFlow::Node nd) {
215243
or
216244
// `import { createRequire } from 'module';`.
217245
// specialized to ES2015 modules to avoid recursion in the `DataFlow::moduleImport()` predicate and to avoid
218-
// negative recursion between `Import.getImportedModuleNode()` and `Import.getImportedModule()`.
219-
exists(ImportDeclaration imp, DataFlow::SourceNode baseObj |
220-
imp.getImportedPath().getValue() = "module"
221-
|
222-
baseObj =
223-
[
224-
DataFlow::destructuredModuleImportNode(imp),
225-
DataFlow::valueNode(imp.getASpecifier().(ImportNamespaceSpecifier))
226-
] and
227-
nd = baseObj.getAPropertyRead("createRequire").getACall()
246+
// negative recursion between `Import.getImportedModuleNode()` and `Import.getImportedModule()`, and
247+
// to avoid depending on `SourceNode` as this would make `SourceNode::Range` recursive.
248+
exists(CallExpr call |
249+
isCreateRequire(call.getCallee().flow()) and
250+
nd = call.flow()
228251
)
229252
}
230253

0 commit comments

Comments
 (0)