mirror of
https://github.com/github/codeql.git
synced 2026-05-22 07:07:09 +02:00
More Module interop code
This commit is contained in:
@@ -1,24 +1,32 @@
|
||||
private import javascript
|
||||
private import PreCallGraphStep as PCG
|
||||
|
||||
class ES2015InteropCall extends DataFlow::CallNode {
|
||||
ES2015InteropCall() {
|
||||
this.getCalleeName() = ["_interopRequireDefault", "_interopRequireWildcard"]
|
||||
}
|
||||
|
||||
private Import getAnImport() {
|
||||
/**
|
||||
* Base class for calls whose first argument is an imported module.
|
||||
*/
|
||||
abstract private class ModuleInteropCall extends DataFlow::CallNode {
|
||||
private Import getImport() {
|
||||
this.getArgument(0).getALocalSource() = result.getImportedModuleNode()
|
||||
}
|
||||
|
||||
Module getImportedModule() { result = this.getAnImport().getImportedModule() }
|
||||
/** Gets the module that is passed as the first argument. */
|
||||
Module getImportedModule() { result = this.getImport().getImportedModule() }
|
||||
|
||||
/** Holds if the imported module is an ES2015 module or a compiled version thereof. */
|
||||
predicate isImportingESModule() {
|
||||
this.getImportedModule() instanceof ES2015Module
|
||||
or
|
||||
exists(this.getImportedModule().getAnExportedValue("__esModule"))
|
||||
}
|
||||
}
|
||||
|
||||
DataFlow::SourceNode getImportedObject() {
|
||||
/** A call that wraps the imported object in a `default` property, unless it is from an ES2015 module. */
|
||||
private class InteropRequireCall extends ModuleInteropCall {
|
||||
InteropRequireCall() {
|
||||
this.getCalleeName() = ["_interopRequireDefault", "_interopRequireWildcard"]
|
||||
}
|
||||
|
||||
DataFlow::SourceNode getImportedObjectRef() {
|
||||
this.isImportingESModule() and
|
||||
result = this
|
||||
or
|
||||
@@ -27,14 +35,42 @@ class ES2015InteropCall extends DataFlow::CallNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that read the `default` property if it exists, otherwise returns the object as-is.
|
||||
*/
|
||||
private class InteropDefaultCall extends ModuleInteropCall {
|
||||
InteropDefaultCall() { this.getCalleeName() = "_interopDefault" }
|
||||
|
||||
DataFlow::Node getDefaultExport() {
|
||||
result = this.getImportedModule().getAnExportedValue("default")
|
||||
}
|
||||
|
||||
DataFlow::Node getImportedObjectSource() {
|
||||
result = this.getDefaultExport()
|
||||
or
|
||||
not exists(this.getDefaultExport()) and
|
||||
result = this.getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
predicate interopModuleStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(ES2015InteropCall call |
|
||||
exists(InteropRequireCall call |
|
||||
pred = call.getArgument(0) and
|
||||
succ = call.getImportedObject()
|
||||
succ = call.getImportedObjectRef()
|
||||
or
|
||||
exists(string prop |
|
||||
pred = call.getImportedModule().getAnExportedValue(prop) and
|
||||
succ = call.getImportedObject().getAPropertyRead(prop)
|
||||
succ = call.getImportedObjectRef().getAPropertyRead(prop)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(InteropDefaultCall call |
|
||||
pred = call.getImportedObjectSource() and
|
||||
succ = call
|
||||
or
|
||||
exists(string prop |
|
||||
pred = call.getDefaultExport().getALocalSource().getAPropertyWrite(prop).getRhs() and
|
||||
succ = call.getAPropertyRead(prop)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user