diff --git a/.github/workflows/check-query-ids.yml b/.github/workflows/check-query-ids.yml new file mode 100644 index 00000000000..9ce9ed5ba85 --- /dev/null +++ b/.github/workflows/check-query-ids.yml @@ -0,0 +1,21 @@ +name: Check query IDs + +on: + pull_request: + paths: + - "**/src/**/*.ql" + - misc/scripts/check-query-ids.py + - .github/workflows/check-query-ids.yml + branches: + - main + - "rc/*" + workflow_dispatch: + +jobs: + check: + name: Check query IDs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check for duplicate query IDs + run: python3 misc/scripts/check-query-ids.py diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 47a2d2bf6ae..de0f11f0521 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -65,6 +65,7 @@ jobs: if : ${{ github.event_name == 'pull_request' }} needs: build-and-test-macos runs-on: macos-12-xl + timeout-minutes: 60 steps: - uses: actions/checkout@v3 - uses: ./swift/actions/run-integration-tests diff --git a/config/identical-files.json b/config/identical-files.json index bc4349f0449..3c332d1d0da 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -470,6 +470,10 @@ "javascript/ql/src/Comments/CommentedOutCodeReferences.inc.qhelp", "python/ql/src/Lexical/CommentedOutCodeReferences.inc.qhelp" ], + "ThreadResourceAbuse qhelp": [ + "java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp", + "java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp" + ], "IDE Contextual Queries": [ "cpp/ql/lib/IDEContextual.qll", "csharp/ql/lib/IDEContextual.qll", @@ -537,6 +541,11 @@ "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll", "python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll" ], + "ApiGraphModelsExtensions": [ + "javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll", + "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll", + "python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll" + ], "TaintedFormatStringQuery Ruby/JS": [ "javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll", "ruby/ql/lib/codeql/ruby/security/TaintedFormatStringQuery.qll" diff --git a/cpp/ql/lib/change-notes/2022-12-08-support-getaddrinfo-dataflow.md b/cpp/ql/lib/change-notes/2022-12-08-support-getaddrinfo-dataflow.md new file mode 100644 index 00000000000..6d1a6499ee9 --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-12-08-support-getaddrinfo-dataflow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `getaddrinfo` function is now recognized as a flow source. diff --git a/cpp/ql/lib/change-notes/2022-12-08-support-scanf-dataflow.md b/cpp/ql/lib/change-notes/2022-12-08-support-scanf-dataflow.md new file mode 100644 index 00000000000..f8382f84c0f --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-12-08-support-scanf-dataflow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `scanf` and `fscanf` functions and their variants are now recognized as flow sources. diff --git a/cpp/ql/lib/change-notes/2022-12-09-generalize-argv-source.md b/cpp/ql/lib/change-notes/2022-12-09-generalize-argv-source.md new file mode 100644 index 00000000000..76fda20ec61 --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-12-09-generalize-argv-source.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `ArgvSource` flow source has been generalized to handle cases where the argument vector of `main` is not named `argv`. diff --git a/cpp/ql/lib/semmle/code/cpp/models/Models.qll b/cpp/ql/lib/semmle/code/cpp/models/Models.qll index 3eed4341cce..1318fd37b7f 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/Models.qll @@ -27,7 +27,7 @@ private import implementations.StdString private import implementations.Swap private import implementations.GetDelim private import implementations.SmartPointer -private import implementations.Sscanf +private import implementations.Scanf private import implementations.Send private import implementations.Recv private import implementations.Accept diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Fread.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Fread.qll index df2d92fbc4f..39733167b81 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Fread.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Fread.qll @@ -15,6 +15,6 @@ private class Fread extends AliasFunction, RemoteFlowSourceFunction { override predicate hasRemoteFlowSource(FunctionOutput output, string description) { output.isParameterDeref(0) and - description = "String read by " + this.getName() + description = "string read by " + this.getName() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll index 67950b6e135..6cf642bd4cb 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll @@ -36,6 +36,6 @@ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectF override predicate hasRemoteFlowSource(FunctionOutput output, string description) { output.isParameterDeref(0) and - description = "String read by " + this.getName() + description = "string read by " + this.getName() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll index 67b9307bbe1..b89eb2c1f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll @@ -49,10 +49,10 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti override predicate hasRemoteFlowSource(FunctionOutput output, string description) { output.isParameterDeref(0) and - description = "String read by " + this.getName() + description = "string read by " + this.getName() or output.isReturnValue() and - description = "String read by " + this.getName() + description = "string read by " + this.getName() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { @@ -98,10 +98,10 @@ private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunctio override predicate hasLocalFlowSource(FunctionOutput output, string description) { output.isParameterDeref(0) and - description = "String read by " + this.getName() + description = "string read by " + this.getName() or output.isReturnValue() and - description = "String read by " + this.getName() + description = "string read by " + this.getName() } override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = 0 } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll index 397dca69fed..c0c4537b746 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll @@ -1,9 +1,10 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.FlowSource private class InetNtoa extends TaintFunction { - InetNtoa() { hasGlobalName("inet_ntoa") } + InetNtoa() { this.hasGlobalName("inet_ntoa") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameter(0) and @@ -12,7 +13,7 @@ private class InetNtoa extends TaintFunction { } private class InetAton extends TaintFunction, ArrayFunction { - InetAton() { hasGlobalName("inet_aton") } + InetAton() { this.hasGlobalName("inet_aton") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and @@ -32,7 +33,7 @@ private class InetAton extends TaintFunction, ArrayFunction { } private class InetAddr extends TaintFunction, ArrayFunction, AliasFunction { - InetAddr() { hasGlobalName("inet_addr") } + InetAddr() { this.hasGlobalName("inet_addr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and @@ -51,7 +52,7 @@ private class InetAddr extends TaintFunction, ArrayFunction, AliasFunction { } private class InetNetwork extends TaintFunction, ArrayFunction { - InetNetwork() { hasGlobalName("inet_network") } + InetNetwork() { this.hasGlobalName("inet_network") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and @@ -64,7 +65,7 @@ private class InetNetwork extends TaintFunction, ArrayFunction { } private class InetMakeaddr extends TaintFunction { - InetMakeaddr() { hasGlobalName("inet_makeaddr") } + InetMakeaddr() { this.hasGlobalName("inet_makeaddr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( @@ -76,7 +77,7 @@ private class InetMakeaddr extends TaintFunction { } private class InetLnaof extends TaintFunction { - InetLnaof() { hasGlobalName("inet_lnaof") } + InetLnaof() { this.hasGlobalName("inet_lnaof") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameter(0) and @@ -85,7 +86,7 @@ private class InetLnaof extends TaintFunction { } private class InetNetof extends TaintFunction { - InetNetof() { hasGlobalName("inet_netof") } + InetNetof() { this.hasGlobalName("inet_netof") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameter(0) and @@ -94,7 +95,7 @@ private class InetNetof extends TaintFunction { } private class InetPton extends TaintFunction, ArrayFunction { - InetPton() { hasGlobalName("inet_pton") } + InetPton() { this.hasGlobalName("inet_pton") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( @@ -114,7 +115,7 @@ private class InetPton extends TaintFunction, ArrayFunction { } private class Gethostbyname extends TaintFunction, ArrayFunction { - Gethostbyname() { hasGlobalName("gethostbyname") } + Gethostbyname() { this.hasGlobalName("gethostbyname") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and @@ -127,7 +128,7 @@ private class Gethostbyname extends TaintFunction, ArrayFunction { } private class Gethostbyaddr extends TaintFunction, ArrayFunction { - Gethostbyaddr() { hasGlobalName("gethostbyaddr") } + Gethostbyaddr() { this.hasGlobalName("gethostbyaddr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( @@ -142,3 +143,21 @@ private class Gethostbyaddr extends TaintFunction, ArrayFunction { override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } } + +private class Getaddrinfo extends TaintFunction, ArrayFunction, RemoteFlowSourceFunction { + Getaddrinfo() { this.hasGlobalName("getaddrinfo") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isParameterDeref([0 .. 2]) and + output.isParameterDeref(3) + } + + override predicate hasArrayInput(int bufParam) { bufParam in [0, 1] } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam in [0, 1] } + + override predicate hasRemoteFlowSource(FunctionOutput output, string description) { + output.isParameterDeref(3) and + description = "address returned by " + this.getName() + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll index 0551185ba14..6a4dd524b86 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll @@ -83,7 +83,7 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, or this.hasGlobalName("recvfrom") and output.isParameterDeref([4, 5]) ) and - description = "Buffer read by " + this.getName() + description = "buffer read by " + this.getName() } override predicate hasSocketInput(FunctionInput input) { input.isParameter(0) } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll similarity index 57% rename from cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll rename to cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll index 42166ae9baa..9a9e02611f8 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Sscanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll @@ -1,6 +1,6 @@ /** - * Provides implementation classes modeling `sscanf`, `fscanf` and various similar - * functions. See `semmle.code.cpp.models.Models` for usage information. + * Provides implementation classes modeling the `scanf` family of functions. + * See `semmle.code.cpp.models.Models` for usage information. */ import semmle.code.cpp.Function @@ -9,18 +9,15 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect +import semmle.code.cpp.models.interfaces.FlowSource /** - * The standard function `sscanf`, `fscanf` and its assorted variants + * The `scanf` family of functions. */ -private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, SideEffectFunction { - SscanfModel() { this instanceof Sscanf or this instanceof Fscanf or this instanceof Snscanf } - +abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, AliasFunction, + SideEffectFunction { override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = this.(ScanfFunction).getFormatParameterIndex() - or - not this instanceof Fscanf and - bufParam = this.(ScanfFunction).getInputParameterIndex() } override predicate hasArrayInput(int bufParam) { this.hasArrayWithNullTerminator(bufParam) } @@ -36,7 +33,7 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S ) } - private int getArgsStartPosition() { result = this.getNumberOfParameters() } + int getArgsStartPosition() { result = this.getNumberOfParameters() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(this.(ScanfFunction).getInputParameterIndex()) and @@ -70,3 +67,36 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S ] } } + +/** + * The standard function `scanf` and its assorted variants + */ +private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction instanceof Scanf { + override predicate hasLocalFlowSource(FunctionOutput output, string description) { + output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and + description = "value read by " + this.getName() + } +} + +/** + * The standard function `fscanf` and its assorted variants + */ +private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction instanceof Fscanf { + override predicate hasRemoteFlowSource(FunctionOutput output, string description) { + output.isParameterDeref(any(int i | i >= this.getArgsStartPosition())) and + description = "value read by " + this.getName() + } +} + +/** + * The standard function `sscanf` and its assorted variants + */ +private class SscanfModel extends ScanfFunctionModel { + SscanfModel() { this instanceof Sscanf or this instanceof Snscanf } + + override predicate hasArrayWithNullTerminator(int bufParam) { + super.hasArrayWithNullTerminator(bufParam) + or + bufParam = this.(ScanfFunction).getInputParameterIndex() + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll index d871bad68af..16047b21183 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Send.qll @@ -58,7 +58,7 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 } override predicate hasRemoteFlowSink(FunctionInput input, string description) { - input.isParameterDeref(1) and description = "Buffer sent by " + this.getName() + input.isParameterDeref(1) and description = "buffer sent by " + this.getName() } override predicate hasSocketInput(FunctionInput input) { input.isParameter(0) } diff --git a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll index 638380c60bf..a63896216a6 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll @@ -50,9 +50,9 @@ private class LocalModelSource extends LocalFlowSource { private class ArgvSource extends LocalFlowSource { ArgvSource() { - exists(Parameter argv | - argv.hasName("argv") and - argv.getFunction().hasGlobalName("main") and + exists(Function main, Parameter argv | + main.hasGlobalName("main") and + main.getParameter(1) = argv and this.asExpr() = argv.getAnAccess() ) } diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index be4f57454aa..f000e25df52 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -16,7 +16,7 @@ import cpp import semmle.code.cpp.security.FunctionWithWrappers -import semmle.code.cpp.security.Security +import semmle.code.cpp.security.FlowSources import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.TaintTracking import DataFlow::PathGraph @@ -47,12 +47,6 @@ class FileFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { arg = 0 } } -Expr asSourceExpr(DataFlow::Node node) { - result = node.asConvertedExpr() - or - result = node.asDefiningArgument() -} - Expr asSinkExpr(DataFlow::Node node) { result = node.asOperand() @@ -89,7 +83,7 @@ predicate hasUpperBoundsCheck(Variable var) { class TaintedPathConfiguration extends TaintTracking::Configuration { TaintedPathConfiguration() { this = "TaintedPathConfiguration" } - override predicate isSource(DataFlow::Node node) { isUserInput(asSourceExpr(node), _) } + override predicate isSource(DataFlow::Node node) { node instanceof FlowSource } override predicate isSink(DataFlow::Node node) { exists(FileFunction fileFunction | @@ -108,31 +102,16 @@ class TaintedPathConfiguration extends TaintTracking::Configuration { hasUpperBoundsCheck(checkedVar) ) } - - predicate hasFilteredFlowPath(DataFlow::PathNode source, DataFlow::PathNode sink) { - this.hasFlowPath(source, sink) and - // The use of `isUserInput` in `isSink` in combination with `asSourceExpr` causes - // duplicate results. Filter these duplicates. The proper solution is to switch to - // using `LocalFlowSource` and `RemoteFlowSource`, but this currently only supports - // a subset of the cases supported by `isUserInput`. - not exists(DataFlow::PathNode source2 | - this.hasFlowPath(source2, sink) and - asSourceExpr(source.getNode()) = asSourceExpr(source2.getNode()) - | - not exists(source.getNode().asConvertedExpr()) and exists(source2.getNode().asConvertedExpr()) - ) - } } from - FileFunction fileFunction, Expr taintedArg, Expr taintSource, TaintedPathConfiguration cfg, - DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, string taintCause, string callChain + FileFunction fileFunction, Expr taintedArg, FlowSource taintSource, TaintedPathConfiguration cfg, + DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, string callChain where taintedArg = asSinkExpr(sinkNode.getNode()) and fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and - cfg.hasFilteredFlowPath(sourceNode, sinkNode) and - taintSource = asSourceExpr(sourceNode.getNode()) and - isUserInput(taintSource, taintCause) + cfg.hasFlowPath(sourceNode, sinkNode) and + taintSource = sourceNode.getNode() select taintedArg, sourceNode, sinkNode, "This argument to a file access function is derived from $@ and then passed to " + callChain + ".", - taintSource, "user input (" + taintCause + ")" + taintSource, "user input (" + taintSource.getSourceType() + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql index 33a6ee1d5f5..2001b1a308c 100644 --- a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql +++ b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql @@ -116,10 +116,6 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration { } } -/** Gets `str` where the first letter has been lowercased. */ -bindingset[str] -string lowerFirst(string str) { result = str.prefix(1).toLowerCase() + str.suffix(1) } - from ImproperArrayIndexValidationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink, string sourceType @@ -128,4 +124,4 @@ where isFlowSource(source.getNode(), sourceType) select sink.getNode(), source, sink, "An array indexing expression depends on $@ that might be outside the bounds of the array.", - source.getNode(), lowerFirst(sourceType) + source.getNode(), sourceType diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index ec78e6b63fb..6858dffbfa8 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -19,7 +19,25 @@ import semmle.code.cpp.ir.dataflow.TaintTracking import DataFlow::PathGraph /** - * A taint flow configuration for flow from user input to a buffer write. + * A buffer write into a sensitive expression. + */ +class SensitiveBufferWrite extends Expr instanceof BufferWrite::BufferWrite { + SensitiveBufferWrite() { super.getDest() instanceof SensitiveExpr } + + /** + * Gets a data source of this operation. + */ + Expr getASource() { result = super.getASource() } + + /** + * Gets the destination buffer of this operation. + */ + Expr getDest() { result = super.getDest() } +} + +/** + * A taint flow configuration for flow from user input to a buffer write + * into a sensitive expression. */ class ToBufferConfiguration extends TaintTracking::Configuration { ToBufferConfiguration() { this = "ToBufferConfiguration" } @@ -31,18 +49,17 @@ class ToBufferConfiguration extends TaintTracking::Configuration { } override predicate isSink(DataFlow::Node sink) { - exists(BufferWrite::BufferWrite w | w.getASource() = sink.asExpr()) + exists(SensitiveBufferWrite w | w.getASource() = sink.asExpr()) } } from - ToBufferConfiguration config, BufferWrite::BufferWrite w, DataFlow::PathNode sourceNode, - DataFlow::PathNode sinkNode, FlowSource source, SensitiveExpr dest + ToBufferConfiguration config, SensitiveBufferWrite w, DataFlow::PathNode sourceNode, + DataFlow::PathNode sinkNode, FlowSource source where config.hasFlowPath(sourceNode, sinkNode) and sourceNode.getNode() = source and - w.getASource() = sinkNode.getNode().asExpr() and - dest = w.getDest() + w.getASource() = sinkNode.getNode().asExpr() select w, sourceNode, sinkNode, - "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@.", source, - "user input (" + source.getSourceType() + ")" + "This write into buffer '" + w.getDest().toString() + "' may contain unencrypted data from $@.", + source, "user input (" + source.getSourceType() + ")" diff --git a/cpp/ql/test/library-tests/dataflow/source-sink-tests/local-flow.ql b/cpp/ql/test/library-tests/dataflow/source-sink-tests/local-flow.ql index c5e2acfae1e..cb687f1d3bf 100644 --- a/cpp/ql/test/library-tests/dataflow/source-sink-tests/local-flow.ql +++ b/cpp/ql/test/library-tests/dataflow/source-sink-tests/local-flow.ql @@ -11,8 +11,20 @@ class LocalFlowSourceTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "local_source" and - value = "" and - exists(LocalFlowSource node | + exists(LocalFlowSource node, int n | + n = + strictcount(LocalFlowSource otherNode | + node.getLocation().getStartLine() = otherNode.getLocation().getStartLine() + ) and + ( + n = 1 and value = "" + or + // If there is more than one node on this line + // we specify the location explicitly. + n > 1 and + value = + node.getLocation().getStartLine().toString() + ":" + node.getLocation().getStartColumn() + ) and location = node.getLocation() and element = node.toString() ) diff --git a/cpp/ql/test/library-tests/dataflow/source-sink-tests/remote-flow.ql b/cpp/ql/test/library-tests/dataflow/source-sink-tests/remote-flow.ql index 08cca02f397..703b62b9ffc 100644 --- a/cpp/ql/test/library-tests/dataflow/source-sink-tests/remote-flow.ql +++ b/cpp/ql/test/library-tests/dataflow/source-sink-tests/remote-flow.ql @@ -11,8 +11,20 @@ class RemoteFlowSourceTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "remote_source" and - value = "" and - exists(RemoteFlowSource node | + exists(RemoteFlowSource node, int n | + n = + strictcount(RemoteFlowSource otherNode | + node.getLocation().getStartLine() = otherNode.getLocation().getStartLine() + ) and + ( + n = 1 and value = "" + or + // If there is more than one node on this line + // we specify the location explicitly. + n > 1 and + value = + node.getLocation().getStartLine().toString() + ":" + node.getLocation().getStartColumn() + ) and location = node.getLocation() and element = node.toString() ) @@ -26,8 +38,20 @@ class RemoteFlowSinkTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "remote_sink" and - value = "" and - exists(RemoteFlowSink node | + exists(RemoteFlowSink node, int n | + n = + strictcount(RemoteFlowSink otherNode | + node.getLocation().getStartLine() = otherNode.getLocation().getStartLine() + ) and + ( + n = 1 and value = "" + or + // If there is more than one node on this line + // we specify the location explicitly. + n > 1 and + value = + node.getLocation().getStartLine().toString() + ":" + node.getLocation().getStartColumn() + ) and location = node.getLocation() and element = node.toString() ) diff --git a/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp b/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp index 423061b80c9..62274096459 100644 --- a/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp +++ b/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp @@ -26,3 +26,27 @@ void test_readv_and_writev(iovec* iovs) { readv(0, iovs, 16); // $ MISSING: remote_source writev(0, iovs, 16); // $ remote_sink } + +struct FILE; + +int fscanf(FILE *stream, const char *format, ...); +int scanf(const char *format, ...); + +void test_scanf(FILE *stream, int *d, char *buf) { + scanf(""); // Not a local source, as there are no output arguments + fscanf(stream, ""); // Not a remote source, as there are no output arguments + scanf("%d", d); // $ local_source + fscanf(stream, "%d", d); // $ remote_source + scanf("%d %s", d, buf); // $ local_source=40:18 local_source=40:21 + fscanf(stream, "%d %s", d, buf); // $ remote_source=41:27 remote_source=41:30 +} + +struct addrinfo; + +int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); + +void test_inet(char *hostname, char *servname, struct addrinfo *hints) { + addrinfo *res; + int ret = getaddrinfo(hostname, servname, hints, &res); // $ remote_source +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected index 194087ce70b..a3ba4f0a5be 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected @@ -203,9 +203,9 @@ subpaths | test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument | #select | test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:51:10:51:16 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv indirection | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument | -| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (String read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument | -| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (String read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument | -| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (String read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument | +| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument | +| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument | +| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument | | test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | Call | Call | | test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | Call | Call | | test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | Convert | Convert | @@ -214,11 +214,11 @@ subpaths | test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ | | test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ | | test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv indirection | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ | -| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (String read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument | -| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (String read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument | -| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (String read by fread) | test.cpp:178:13:178:19 | strncat output argument | strncat output argument | -| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (String read by fread) | test.cpp:180:13:180:19 | strncat output argument | strncat output argument | -| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument | -| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument | -| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument | -| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument | +| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument | +| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument | +| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:178:13:178:19 | strncat output argument | strncat output argument | +| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:180:13:180:19 | strncat output argument | strncat output argument | +| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (string read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument | +| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:194:9:194:16 | fread output argument | user input (string read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument | +| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (string read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument | +| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | Convert indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:218:9:218:16 | fread output argument | user input (string read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected index 2dd4bf12bd7..7aca640ad8c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected @@ -8,6 +8,6 @@ nodes | test.cpp:58:25:58:29 | input | semmle.label | input | subpaths #select -| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets | user input (String read by gets) | -| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:8:110:15 | gets output argument | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:8:110:15 | gets output argument | user input (String read by gets) | +| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets | user input (string read by gets) | +| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:8:110:15 | gets output argument | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:8:110:15 | gets output argument | user input (string read by gets) | | test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:54:17:54:20 | argv | user input (a command-line argument) | diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj index ec2aae685e8..981ea925b77 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj @@ -15,7 +15,7 @@ - + diff --git a/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml b/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml index 9d4afaacbf7..1bf56eecf70 100644 --- a/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml +++ b/csharp/ql/lib/ext/generated/dotnet_runtime.model.yml @@ -10195,7 +10195,7 @@ extensions: - addsTo: pack: codeql/csharp-all - extensible: extNegativeSummaryModel + extensible: extNeutralModel data: - ["AssemblyStripper", "AssemblyStripper", "StripAssembly", "(System.String,System.String)", "generated"] - ["Generators", "EventSourceGenerator", "Execute", "(Microsoft.CodeAnalysis.GeneratorExecutionContext)", "generated"] diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll index f72fa288919..2664c25280b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll @@ -11,9 +11,9 @@ * `namespace; type; subtypes; name; signature; ext; input; kind; provenance` * - Summaries: * `namespace; type; subtypes; name; signature; ext; input; output; kind; provenance` - * - Negative Summaries: + * - Neutrals: * `namespace; type; name; signature; provenance` - * A negative summary is used to indicate that there is no flow via a callable. + * A neutral is used to indicate that there is no flow via a callable. * * The interpretation of a row is similar to API-graphs with a left-to-right * reading. @@ -132,30 +132,12 @@ private class SummaryModelCsvInternal extends Unit { abstract predicate row(string row); } -/** - * DEPRECATED: Define negative summary models as data extensions instead. - * - * A unit class for adding additional negative summary model rows. - * - * Extend this class to add additional negative summary definitions. - */ -deprecated class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal; - -private class NegativeSummaryModelCsvInternal extends Unit { - /** Holds if `row` specifies a negative summary definition. */ - abstract predicate row(string row); -} - private predicate sourceModelInternal(string row) { any(SourceModelCsvInternal s).row(row) } private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal s).row(row) } private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -private predicate negativeSummaryModelInternal(string row) { - any(NegativeSummaryModelCsvInternal s).row(row) -} - /** * Holds if a source model exists for the given parameters. */ @@ -243,25 +225,16 @@ predicate summaryModel( extSummaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) } -/** Holds if a summary model exists indicating there is no flow for the given parameters. */ -extensible predicate extNegativeSummaryModel( +/** Holds if a model exists indicating there is no flow for the given parameters. */ +extensible predicate extNeutralModel( string namespace, string type, string name, string signature, string provenance ); -/** Holds if a summary model exists indicating there is no flow for the given parameters. */ -predicate negativeSummaryModel( +/** Holds if a model exists indicating there is no flow for the given parameters. */ +predicate neutralModel( string namespace, string type, string name, string signature, string provenance ) { - exists(string row | - negativeSummaryModelInternal(row) and - row.splitAt(";", 0) = namespace and - row.splitAt(";", 1) = type and - row.splitAt(";", 2) = name and - row.splitAt(";", 3) = signature and - row.splitAt(";", 4) = provenance - ) - or - extNegativeSummaryModel(namespace, type, name, signature, provenance) + extNeutralModel(namespace, type, name, signature, provenance) } private predicate relevantNamespace(string namespace) { @@ -393,8 +366,6 @@ module ModelValidation { sinkModelInternal(row) and expect = 9 and pred = "sink" or summaryModelInternal(row) and expect = 10 and pred = "summary" - or - negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and @@ -418,9 +389,9 @@ module ModelValidation { summaryModel(namespace, type, _, name, signature, ext, _, _, _, provenance) and pred = "summary" or - negativeSummaryModel(namespace, type, name, signature, provenance) and + neutralModel(namespace, type, name, signature, provenance) and ext = "" and - pred = "negative summary" + pred = "neutral" | not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and result = "Dubious namespace \"" + namespace + "\" in " + pred + " model." @@ -461,7 +432,7 @@ private predicate elementSpec( or summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or - negativeSummaryModel(namespace, type, name, signature, _) and ext = "" and subtypes = false + neutralModel(namespace, type, name, signature, _) and ext = "" and subtypes = false } private predicate elementSpec( @@ -595,7 +566,7 @@ private Element interpretElement0( ) } -/** Gets the source/sink/summary/negativesummary element corresponding to the supplied parameters. */ +/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */ Element interpretElement( string namespace, string type, boolean subtypes, string name, string signature, string ext ) { diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 845d5bd378a..12dd22f24ff 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2321,8 +2321,8 @@ module Csv { ) } - /** Computes the first 4 columns for negative CSV rows of `c`. */ - string asPartialNegativeModel(DotNet::Callable c) { + /** Computes the first 4 columns for neutral CSV rows of `c`. */ + string asPartialNeutralModel(DotNet::Callable c) { exists(string namespace, string type, string name, string parameters | partialModel(c, namespace, type, name, parameters) and result = diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll index 93cd70f63c2..44baca91929 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll @@ -121,12 +121,12 @@ predicate summaryElement(Callable c, string input, string output, string kind, b } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the neutral model is autogenerated. */ -predicate negativeSummaryElement(Callable c, boolean generated) { +predicate neutralElement(Callable c, boolean generated) { exists(string namespace, string type, string name, string signature, string provenance | - negativeSummaryModel(namespace, type, name, signature, provenance) and + neutralModel(namespace, type, name, signature, provenance) and generated = isGenerated(provenance) and c = interpretElement(namespace, type, false, name, signature, "") ) diff --git a/csharp/ql/src/Telemetry/SupportedExternalApis.ql b/csharp/ql/src/Telemetry/SupportedExternalApis.ql index 039f2a24677..7bf48bfe4a4 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalApis.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalApis.ql @@ -15,7 +15,7 @@ private predicate relevant(ExternalApi api) { not api.isUninteresting() and ( api.isSupported() or - api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable + api instanceof FlowSummaryImpl::Public::NeutralCallable ) } diff --git a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql index 618f26e6636..9466ed8c1d1 100644 --- a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -14,7 +14,7 @@ private import ExternalApi private predicate relevant(ExternalApi api) { not api.isUninteresting() and not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable + not api instanceof FlowSummaryImpl::Public::NeutralCallable } from string info, int usages diff --git a/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql b/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql index 4eef46ef86b..3e9802f60af 100644 --- a/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/meta/frameworks/UnsupportedExternalAPIs.ql @@ -18,5 +18,5 @@ where c.getTarget().getUnboundDeclaration() = api and not api.isUninteresting() and not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable + not api instanceof FlowSummaryImpl::Public::NeutralCallable select c, "Call to unsupported external API $@.", api, api.toString() diff --git a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureNeutralModels.ql similarity index 66% rename from csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql rename to csharp/ql/src/utils/model-generator/CaptureNeutralModels.ql index 9188b54ef40..9cf2b81ba7c 100644 --- a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureNeutralModels.ql @@ -1,8 +1,8 @@ /** - * @name Capture negative summary models. - * @description Finds negative summary models to be used by other queries. + * @name Capture neutral models. + * @description Finds neutral models to be used by other queries. * @kind diagnostic - * @id cs/utils/model-generator/negative-summary-models + * @id cs/utils/model-generator/neutral-models * @tags model-generator */ diff --git a/csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql b/csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql similarity index 50% rename from csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql rename to csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql index 53681f5f684..5ca6ef9579c 100644 --- a/csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql +++ b/csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql @@ -1,7 +1,7 @@ /** - * @name Extract MaD negative summary model rows. - * @description This extracts the Models as data negative summary model rows. - * @id csharp/utils/modelconverter/generate-data-extensions-negative-summary + * @name Extract MaD neutral model rows. + * @description This extracts the Models as data neutral model rows. + * @id csharp/utils/modelconverter/generate-data-extensions-neutral */ import csharp @@ -9,6 +9,6 @@ import semmle.code.csharp.dataflow.ExternalFlow from string package, string type, string name, string signature, string provenance where - negativeSummaryModel(package, type, name, signature, provenance) and + neutralModel(package, type, name, signature, provenance) and provenance != "generated" select package, type, name, signature, provenance order by package, type, name, signature diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index f40b028ba6d..893c62191b3 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -58,9 +58,7 @@ private string asSummaryModel(TargetApiSpecific api, string input, string output + "generated" } -string asNegativeSummaryModel(TargetApiSpecific api) { - result = asPartialNegativeModel(api) + "generated" -} +string asNeutralModel(TargetApiSpecific api) { result = asPartialNeutralModel(api) + "generated" } /** * Gets the value summary model for `api` with `input` and `output`. diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index c3d520154a4..3e1a303d5bb 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -68,7 +68,7 @@ class TargetApiSpecific extends DotNet::Callable { predicate asPartialModel = DataFlowPrivate::Csv::asPartialModel/1; -predicate asPartialNegativeModel = DataFlowPrivate::Csv::asPartialNegativeModel/1; +predicate asPartialNeutralModel = DataFlowPrivate::Csv::asPartialNeutralModel/1; /** * Holds if `t` is a type that is generally used for bulk data in collection types. diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll index 2f16baec794..1ed6b9a4850 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll @@ -85,10 +85,10 @@ string captureFlow(DataFlowTargetApi api) { } /** - * Gets the negative summary for `api`, if any. - * A negative summary is generated, if there does not exist any positive flow. + * Gets the neutral model for `api`, if any. + * A neutral model is generated, if there does not exist summary model. */ string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and - result = asNegativeSummaryModel(api) + result = asNeutralModel(api) } diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index fcdf91118e1..ad09add3853 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -11928,7 +11928,7 @@ summary | System;ValueTuple<>;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System;ValueTuple<>;false;ValueTuple;(T1);;Argument[0];Argument[this].Field[System.ValueTuple<>.Item1];value;manual | | System;ValueTuple<>;false;get_Item;(System.Int32);;Argument[this].Field[System.ValueTuple<>.Item1];ReturnValue;value;manual | -negativeSummary +neutral | Microsoft.CSharp.RuntimeBinder;CSharpArgumentInfo;Create;(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,System.String);generated | | Microsoft.CSharp.RuntimeBinder;RuntimeBinderException;RuntimeBinderException;();generated | | Microsoft.CSharp.RuntimeBinder;RuntimeBinderException;RuntimeBinderException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql index 717c4943f46..679c4bbf0ef 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql @@ -6,11 +6,9 @@ private class IncludeAllSummarizedCallable extends IncludeSummarizedCallable { IncludeAllSummarizedCallable() { exists(this) } } -private class IncludeNegativeSummarizedCallable extends RelevantNegativeSummarizedCallable { - IncludeNegativeSummarizedCallable() { - this instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable - } +private class IncludeNeutralCallable extends RelevantNeutralCallable { + IncludeNeutralCallable() { this instanceof FlowSummaryImpl::Public::NeutralCallable } /** Gets a string representing the callable in semi-colon separated format for use in flow summaries. */ - final override string getCallableCsv() { result = Csv::asPartialNegativeModel(this) } + final override string getCallableCsv() { result = Csv::asPartialNeutralModel(this) } } diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected index 7ad542d4668..880a71ca5d0 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected @@ -10262,4 +10262,4 @@ summary | System;ValueTuple<>;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System;ValueTuple<>;false;ValueTuple;(T1);;Argument[0];Argument[this].Field[System.ValueTuple<>.Item1];value;manual | | System;ValueTuple<>;false;get_Item;(System.Int32);;Argument[this].Field[System.ValueTuple<>.Item1];ReturnValue;value;manual | -negativeSummary +neutral diff --git a/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.expected b/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.expected index ae10cc17e9d..2d5a35839fb 100644 --- a/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.expected @@ -131,7 +131,7 @@ summary | System.Data.Entity;DbSet<>;false;AttachRange;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].Element;value;manual | | System.Data.Entity;DbSet<>;false;Update;(T);;Argument[0];Argument[this].Element;value;manual | | System.Data.Entity;DbSet<>;false;UpdateRange;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].Element;value;manual | -negativeSummary +neutral sourceNode sinkNode | EntityFrameworkCore.cs:72:36:72:40 | "sql" | sql | diff --git a/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref deleted file mode 100644 index c24d124c0b2..00000000000 --- a/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/model-generator/CaptureNegativeSummaryModels.ql \ No newline at end of file diff --git a/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.expected diff --git a/csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref new file mode 100644 index 00000000000..cb6ef7faa65 --- /dev/null +++ b/csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref @@ -0,0 +1 @@ +utils/model-generator/CaptureNeutralModels.ql \ No newline at end of file diff --git a/docs/codeql/README.rst b/docs/codeql/README.rst index d27fe2189d2..a07d15c27e1 100644 --- a/docs/codeql/README.rst +++ b/docs/codeql/README.rst @@ -42,9 +42,10 @@ For more information, see Building and previewing the CodeQL documentation ************************************************ -To build and preview the documentation and training presentations locally, you need to -install Sphinx 1.7.9. More recent versions of Sphinx do not work with hieroglyph, -the Sphinx extension that we use to generate HTML slides, as explained below. +To build and preview the documentation and training presentations locally, you need to +install Sphinx 1.7.9 using Python 2 (for example: `pip install sphinx==1.7.9`). +More recent versions of Sphinx do not work with hieroglyph, +the Sphinx extension that we use to generate HTML slides, as explained below. For installation options, see https://github.com/sphinx-doc/sphinx. diff --git a/docs/codeql/writing-codeql-queries/river-answer-1-path.ql b/docs/codeql/writing-codeql-queries/river-answer-1-path.ql index a951f65ab04..0a90c85faf2 100644 --- a/docs/codeql/writing-codeql-queries/river-answer-1-path.ql +++ b/docs/codeql/writing-codeql-queries/river-answer-1-path.ql @@ -6,14 +6,11 @@ /** A possible cargo item. */ class Cargo extends string { Cargo() { - this = "Nothing" or - this = "Goat" or - this = "Cabbage" or - this = "Wolf" + this = ["Nothing", "Goat", "Cabbage", "Wolf"] } } - /** One of two shores. */ + /** A shore, named either `Left` or `Right`. */ class Shore extends string { Shore() { this = "Left" or @@ -93,7 +90,7 @@ class Cargo extends string { // Reachable by first following pathSoFar and then ferrying cargo exists(string pathSoFar, string visitedStatesSoFar, Cargo cargo | result = this.reachesVia(pathSoFar, visitedStatesSoFar).safeFerry(cargo) and - not exists(int i | i = visitedStatesSoFar.indexOf(result)) and // resulting state is not visited yet + not exists(visitedStatesSoFar.indexOf(result)) and // resulting state is not visited yet visitedStates = visitedStatesSoFar + "_" + result and path = pathSoFar + ",\nthen " + cargo + " is ferried " + result.towards() ) diff --git a/docs/codeql/writing-codeql-queries/river-answer-2-abstract-class.ql b/docs/codeql/writing-codeql-queries/river-answer-2-abstract-class.ql index 78676101180..02ae9c9bb69 100644 --- a/docs/codeql/writing-codeql-queries/river-answer-2-abstract-class.ql +++ b/docs/codeql/writing-codeql-queries/river-answer-2-abstract-class.ql @@ -154,7 +154,7 @@ class Shore extends string { State reachesVia(string path) { exists(string pathSoFar | result = this.reachesVia(pathSoFar).transition() and - not exists(int i | i = pathSoFar.indexOf(result.toString())) and + not exists(pathSoFar.indexOf(result.toString())) and path = pathSoFar + "\n↓\n" + result ) } @@ -169,7 +169,7 @@ class Shore extends string { } override State reachesVia(string path) { - path = this + "\n↓\n" + result and result = transition() + path = this + "\n↓\n" + result and result = this.transition() or result = super.reachesVia(path) } diff --git a/docs/codeql/writing-codeql-queries/river-answer-3-datatypes.ql b/docs/codeql/writing-codeql-queries/river-answer-3-datatypes.ql index e17d46f1aba..6200da9ebc2 100644 --- a/docs/codeql/writing-codeql-queries/river-answer-3-datatypes.ql +++ b/docs/codeql/writing-codeql-queries/river-answer-3-datatypes.ql @@ -118,7 +118,7 @@ class State extends TState { State reachesVia(string path) { exists(string pathSoFar | result = this.reachesVia(pathSoFar).transition() and - not exists(int i | i = pathSoFar.indexOf(result.toString())) and + not exists(pathSoFar.indexOf(result.toString())) and path = pathSoFar + "\n" + result ) } @@ -133,7 +133,7 @@ class InitialState extends State { } override State reachesVia(string path) { - path = this + "\n" + result and result = transition() + path = this + "\n" + result and result = this.transition() or result = super.reachesVia(path) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll index 5087403f3b4..0797cd7a979 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll @@ -76,11 +76,11 @@ predicate summaryElement( } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. - * Note. Negative flow summaries has not been implemented for Go. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the model is autogenerated. + * Note. Neutral models have not been implemented for Go. */ -predicate negativeSummaryElement(SummarizedCallable c, boolean generated) { none() } +predicate neutralElement(SummarizedCallable c, boolean generated) { none() } /** Gets the summary component for specification component `c`, if any. */ bindingset[c] diff --git a/java/kotlin-extractor/src/main/kotlin/ExternalDeclExtractor.kt b/java/kotlin-extractor/src/main/kotlin/ExternalDeclExtractor.kt index 1b65c8e6f2b..c45e0a454b7 100644 --- a/java/kotlin-extractor/src/main/kotlin/ExternalDeclExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/ExternalDeclExtractor.kt @@ -119,7 +119,7 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false) } else { - fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false) + fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false, extractAnnotations = true) } } } diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinExtractorExtension.kt b/java/kotlin-extractor/src/main/kotlin/KotlinExtractorExtension.kt index 71e1862a22e..9bfcabd20fb 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinExtractorExtension.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinExtractorExtension.kt @@ -207,6 +207,7 @@ class KotlinExtractorGlobalState { val syntheticToRealClassMap = HashMap() val syntheticToRealFunctionMap = HashMap() val syntheticToRealFieldMap = HashMap() + val syntheticRepeatableAnnotationContainers = HashMap() } /* diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 4683731d8e9..faa83139bbb 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2,9 +2,7 @@ package com.github.codeql import com.github.codeql.comments.CommentExtractor import com.github.codeql.utils.* -import com.github.codeql.utils.versions.allOverriddenIncludingSelf -import com.github.codeql.utils.versions.functionN -import com.github.codeql.utils.versions.isUnderscoreParameter +import com.github.codeql.utils.versions.* import com.semmle.extractor.java.OdasaOutput import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.parents @@ -16,17 +14,46 @@ import org.jetbrains.kotlin.descriptors.java.JavaVisibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.ir.util.companionObject +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.ir.util.hasInterfaceParent +import org.jetbrains.kotlin.ir.util.isAnnotationClass +import org.jetbrains.kotlin.ir.util.isAnonymousObject +import org.jetbrains.kotlin.ir.util.isFakeOverride +import org.jetbrains.kotlin.ir.util.isFunctionOrKFunction +import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.util.isLocal +import org.jetbrains.kotlin.ir.util.isNonCompanionObject +import org.jetbrains.kotlin.ir.util.isObject +import org.jetbrains.kotlin.ir.util.isSuspend +import org.jetbrains.kotlin.ir.util.isSuspendFunctionOrKFunction +import org.jetbrains.kotlin.ir.util.isVararg +import org.jetbrains.kotlin.ir.util.kotlinFqName +import org.jetbrains.kotlin.ir.util.packageFqName +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.parentClassOrNull +import org.jetbrains.kotlin.ir.util.primaryConstructor +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.target +import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS +import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS import org.jetbrains.kotlin.load.java.sources.JavaSourceElement +import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaClass +import org.jetbrains.kotlin.load.java.structure.JavaConstructor import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner @@ -34,6 +61,7 @@ import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.io.Closeable import java.util.* import kotlin.collections.ArrayList @@ -51,6 +79,8 @@ open class KotlinFileExtractor( globalExtensionState: KotlinExtractorGlobalState, ): KotlinUsesExtractor(logger, tw, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState) { + val metaAnnotationSupport = MetaAnnotationSupport(logger, pluginContext, this) + private inline fun with(kind: String, element: IrElement, f: () -> T): T { val name = when (element) { is IrFile -> element.name @@ -91,7 +121,7 @@ open class KotlinFileExtractor( } file.declarations.forEach { - extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) + extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true, extractAnnotations = true) if (it is IrProperty || it is IrField || it is IrFunction) { externalClassExtractor.writeStubTrapFile(it, getTrapFileSignature(it)) } @@ -148,7 +178,7 @@ open class KotlinFileExtractor( private fun shouldExtractDecl(declaration: IrDeclaration, extractPrivateMembers: Boolean) = extractPrivateMembers || !isPrivate(declaration) - fun extractDeclaration(declaration: IrDeclaration, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) { + fun extractDeclaration(declaration: IrDeclaration, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean, extractAnnotations: Boolean) { with("declaration", declaration) { if (!shouldExtractDecl(declaration, extractPrivateMembers)) return @@ -163,7 +193,7 @@ open class KotlinFileExtractor( is IrFunction -> { val parentId = useDeclarationParent(declaration.parent, false)?.cast() if (parentId != null) { - extractFunction(declaration, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, null, listOf()) + extractFunction(declaration, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = extractAnnotations, null, listOf()) } Unit } @@ -173,7 +203,7 @@ open class KotlinFileExtractor( is IrProperty -> { val parentId = useDeclarationParent(declaration.parent, false)?.cast() if (parentId != null) { - extractProperty(declaration, parentId, extractBackingField = true, extractFunctionBodies = extractFunctionBodies, extractPrivateMembers = extractPrivateMembers, null, listOf()) + extractProperty(declaration, parentId, extractBackingField = true, extractFunctionBodies = extractFunctionBodies, extractPrivateMembers = extractPrivateMembers, extractAnnotations = extractAnnotations, null, listOf()) } Unit } @@ -187,7 +217,8 @@ open class KotlinFileExtractor( is IrField -> { val parentId = useDeclarationParent(getFieldParent(declaration), false)?.cast() if (parentId != null) { - extractField(declaration, parentId) + // For consistency with the Java extractor, enum entries get type accesses only if we're extracting from .kt source (i.e., when `extractFunctionBodies` is set) + extractField(declaration, parentId, extractAnnotationEnumTypeAccesses = extractFunctionBodies) } Unit } @@ -238,6 +269,8 @@ open class KotlinFileExtractor( addModifiers(id, "out") } + // extractAnnotations(tp, id) + // TODO: introduce annotations once they can be disambiguated from bounds, which are also child expressions. return id } } @@ -405,8 +438,8 @@ open class KotlinFileExtractor( } } when (d) { - is IrFunction -> extractFunction(d, parentId, extractBody = false, extractMethodAndParameterTypeAccesses = false, typeParamSubstitution, argsIncludingOuterClasses) - is IrProperty -> extractProperty(d, parentId, extractBackingField = false, extractFunctionBodies = false, extractPrivateMembers = false, typeParamSubstitution, argsIncludingOuterClasses) + is IrFunction -> extractFunction(d, parentId, extractBody = false, extractMethodAndParameterTypeAccesses = false, extractAnnotations = false, typeParamSubstitution, argsIncludingOuterClasses) + is IrProperty -> extractProperty(d, parentId, extractBackingField = false, extractFunctionBodies = false, extractPrivateMembers = false, extractAnnotations = false, typeParamSubstitution, argsIncludingOuterClasses) else -> {} } } @@ -457,7 +490,137 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - val jvmStaticFqName = FqName("kotlin.jvm.JvmStatic") + private val javaLangDeprecated by lazy { referenceExternalClass("java.lang.Deprecated") } + + private val javaLangDeprecatedConstructor by lazy { javaLangDeprecated?.constructors?.singleOrNull() } + + private fun replaceKotlinDeprecatedAnnotation(annotations: List): List { + val shouldReplace = + annotations.any { (it.type as? IrSimpleType)?.classFqName?.asString() == "kotlin.Deprecated" } && + annotations.none { it.type.classOrNull == javaLangDeprecated?.symbol } + val jldConstructor = javaLangDeprecatedConstructor + if (!shouldReplace || jldConstructor == null) + return annotations + return annotations.filter { (it.type as? IrSimpleType)?.classFqName?.asString() != "kotlin.Deprecated" } + + // Note we lose any arguments to @java.lang.Deprecated that were written in source. + IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, jldConstructor.returnType, jldConstructor.symbol, 0 + ) + } + + private fun extractAnnotations(c: IrAnnotationContainer, annotations: List, parent: Label, extractEnumTypeAccesses: Boolean) { + val origin = (c as? IrDeclaration)?.origin ?: run { logger.warn("Unexpected annotation container: $c"); return } + val replacedAnnotations = + if (origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) + replaceKotlinDeprecatedAnnotation(annotations) + else + annotations + val groupedAnnotations = metaAnnotationSupport.groupRepeatableAnnotations(replacedAnnotations) + for ((idx, constructorCall: IrConstructorCall) in groupedAnnotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { + extractAnnotation(constructorCall, parent, idx, extractEnumTypeAccesses) + } + } + + private fun extractAnnotations(c: IrAnnotationContainer, parent: Label, extractEnumTypeAccesses: Boolean) { + extractAnnotations(c, c.annotations, parent, extractEnumTypeAccesses) + } + + private fun extractAnnotation( + constructorCall: IrConstructorCall, + parent: Label, + idx: Int, + extractEnumTypeAccesses: Boolean, + contextLabel: String? = null + ): Label { + // Erase the type here because the JVM lowering erases the annotation type, and so the Java extractor will see it in erased form. + val t = useType(erase(constructorCall.type)) + val annotationContextLabel = contextLabel ?: "{${t.javaResult.id}}" + val id = tw.getLabelFor("@\"annotation;{$parent};$annotationContextLabel\"") + tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, t.kotlinResult.id) + + val locId = tw.getLocation(constructorCall) + tw.writeHasLocation(id, locId) + + for (i in 0 until constructorCall.valueArgumentsCount) { + val param = constructorCall.symbol.owner.valueParameters[i] + val prop = constructorCall.symbol.owner.parentAsClass.declarations + .filterIsInstance() + .first { it.name == param.name } + val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression + val getter = prop.getter + if (getter == null) { + logger.warnElement("Expected annotation property to define a getter", prop) + } else { + val getterId = useFunction(getter) + val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType, extractEnumTypeAccesses) + if (exprId != null) { + tw.writeAnnotValue(id, getterId, exprId) + } + } + } + return id + } + + private fun extractAnnotationValueExpression( + v: IrExpression?, + parent: Label, + idx: Int, + contextLabel: String, + contextType: IrType?, + extractEnumTypeAccesses: Boolean): Label? { + + fun exprId() = tw.getLabelFor("@\"annotationExpr;{$parent};$idx\"") + + return when (v) { + is IrConst<*> -> { + extractConstant(v, parent, idx, null, null, overrideId = exprId()) + } + is IrGetEnumValue -> { + extractEnumValue(v, parent, idx, null, null, extractTypeAccess = extractEnumTypeAccesses, overrideId = exprId()) + } + is IrClassReference -> { + val classRefId = exprId() + val typeAccessId = tw.getLabelFor("@\"annotationExpr;{$classRefId};0\"") + extractClassReference(v, parent, idx, null, null, overrideId = classRefId, typeAccessOverrideId = typeAccessId, useJavaLangClassType = true) + } + is IrConstructorCall -> { + extractAnnotation(v, parent, idx, extractEnumTypeAccesses, contextLabel) + } + is IrVararg -> { + tw.getLabelFor("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> + // Use the context type (i.e., the type the annotation expects, not the actual type of the array) + // because the Java extractor fills in array types using the same technique. These should only + // differ for generic annotations. + if (contextType == null) { + logger.warnElement("Expected an annotation array to have an enclosing context", v) + } else { + val type = useType(kClassToJavaClass(contextType)) + tw.writeExprs_arrayinit(arrayId, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(arrayId, type.kotlinResult.id) + tw.writeHasLocation(arrayId, tw.getLocation(v)) + + v.elements.forEachIndexed { index, irVarargElement -> run { + val argExpr = when (irVarargElement) { + is IrExpression -> irVarargElement + is IrSpreadElement -> irVarargElement.expression + else -> { + logger.errorElement("Unrecognised IrVarargElement: " + irVarargElement.javaClass, irVarargElement) + null + } + } + extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null, extractEnumTypeAccesses) + } } + } + } + } + // is IrErrorExpression + // null + // Note: emitting an ErrorExpr here would induce an inconsistency if this annotation is later seen from source or by the Java extractor, + // in both of which cases the real value will get extracted. + else -> null + } + } fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label { with("class source", c) { @@ -470,6 +633,10 @@ open class KotlinFileExtractor( if (c.isInterfaceLike) { val interfaceId = id.cast() tw.writeInterfaces(interfaceId, cls, pkgId, interfaceId) + + if (c.kind == ClassKind.ANNOTATION_CLASS) { + tw.writeIsAnnotType(interfaceId) + } } else { val classId = id.cast() tw.writeClasses(classId, cls, pkgId, classId) @@ -495,10 +662,25 @@ open class KotlinFileExtractor( c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx, javaClass?.typeParameters?.getOrNull(idx)) } if (extractDeclarations) { - c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) } - if (extractStaticInitializer) - extractStaticInitializer(c, { id }) - extractJvmStaticProxyMethods(c, id, extractPrivateMembers, extractFunctionBodies) + if (c.kind == ClassKind.ANNOTATION_CLASS) { + c.declarations + .filterIsInstance() + .forEach { + val getter = it.getter + if (getter == null) { + logger.warnElement("Expected an annotation property to have a getter", it) + } else { + extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = true, null, listOf())?.also { functionLabel -> + tw.writeIsAnnotElem(functionLabel.cast()) + } + } + } + } else { + c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies, extractAnnotations = true) } + if (extractStaticInitializer) + extractStaticInitializer(c, { id }) + extractJvmStaticProxyMethods(c, id, extractPrivateMembers, extractFunctionBodies) + } } if (c.isNonCompanionObject) { // For `object MyObject { ... }`, the .class has an @@ -526,6 +708,14 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(c, id) + val additionalAnnotations = + if (c.kind == ClassKind.ANNOTATION_CLASS && c.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) + metaAnnotationSupport.generateJavaMetaAnnotations(c, extractFunctionBodies) + else + listOf() + + extractAnnotations(c, c.annotations + additionalAnnotations, id, extractFunctionBodies) + if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) @@ -534,6 +724,8 @@ open class KotlinFileExtractor( } } + val jvmStaticFqName = FqName("kotlin.jvm.JvmStatic") + private fun extractJvmStaticProxyMethods(c: IrClass, classId: Label, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) { // Add synthetic forwarders for any JvmStatic methods or properties: @@ -547,7 +739,7 @@ open class KotlinFileExtractor( val proxyFunctionId = tw.getLabelFor(getFunctionLabel(f, classId, listOf())) // We extract the function prototype with its ID overridden to belong to `c` not the companion object, // but suppress outputting the body, which we will replace with a delegating call below. - forceExtractFunction(f, classId, extractBody = false, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution = null, classTypeArgsIncludingOuterClasses = listOf(), extractOrigin = false, OverriddenFunctionAttributes(id = proxyFunctionId)) + forceExtractFunction(f, classId, extractBody = false, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = false, typeSubstitution = null, classTypeArgsIncludingOuterClasses = listOf(), extractOrigin = false, OverriddenFunctionAttributes(id = proxyFunctionId)) addModifiers(proxyFunctionId, "static") tw.writeCompiler_generated(proxyFunctionId, CompilerGeneratedKinds.JVMSTATIC_PROXY_METHOD.kind) if (extractFunctionBodies) { @@ -714,6 +906,13 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) + val javaParameter = when(val callable = (vp.parent as? IrFunction)?.let { getJavaCallable(it) }) { + is JavaConstructor -> callable.valueParameters.getOrNull(idx) + is JavaMethod -> callable.valueParameters.getOrNull(idx) + else -> null + } + val extraAnnotations = listOfNotNull(getNullabilityAnnotation(vp.type, vp.origin, vp.annotations, javaParameter?.annotations)) + extractAnnotations(vp, vp.annotations + extraAnnotations, id, extractTypeAccess) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -891,7 +1090,7 @@ open class KotlinFileExtractor( f.realOverrideTarget.let { it != f && (it as? IrSimpleFunction)?.modality != Modality.ABSTRACT && isKotlinDefinedInterface(it.parentClassOrNull) } private fun makeInterfaceForwarder(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) = - forceExtractFunction(f, parentId, extractBody = false, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = OverriddenFunctionAttributes(visibility = DescriptorVisibilities.PUBLIC)).also { functionId -> + forceExtractFunction(f, parentId, extractBody = false, extractMethodAndParameterTypeAccesses, extractAnnotations = false, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = OverriddenFunctionAttributes(visibility = DescriptorVisibilities.PUBLIC, modality = Modality.OPEN)).also { functionId -> tw.writeCompiler_generated(functionId, CompilerGeneratedKinds.INTERFACE_FORWARDER.kind) if (extractBody) { val realFunctionLocId = tw.getLocation(f) @@ -932,7 +1131,7 @@ open class KotlinFileExtractor( } } - private fun extractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) = + private fun extractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, extractAnnotations: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) = if (isFake(f)) { if (needsInterfaceForwarder(f)) makeInterfaceForwarder(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses) @@ -941,7 +1140,7 @@ open class KotlinFileExtractor( } else { // Work around an apparent bug causing redeclarations of `fun toString(): String` specifically in interfaces loaded from Java classes show up like fake overrides. val overriddenVisibility = if (f.isFakeOverride && isJavaBinaryObjectMethodRedeclaration(f)) OverriddenFunctionAttributes(visibility = DescriptorVisibilities.PUBLIC) else null - forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = overriddenVisibility).also { + forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, extractAnnotations, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = overriddenVisibility).also { // The defaults-forwarder function is a static utility, not a member, so we only need to extract this for the unspecialised instance of this class. if (classTypeArgsIncludingOuterClasses.isNullOrEmpty()) extractDefaultsFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses) @@ -957,7 +1156,7 @@ open class KotlinFileExtractor( val locId = getLocation(f, null) val extReceiver = f.extensionReceiverParameter val dispatchReceiver = if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter - val parameterTypes = listOfNotNull(extReceiver?.let { erase(it.type) }) + getDefaultsMethodArgTypes(f) + val parameterTypes = getDefaultsMethodArgTypes(f) val allParamTypeResults = parameterTypes.mapIndexed { i, paramType -> val paramId = tw.getLabelFor(getValueParameterLabel(id, i)) extractValueParameter(paramId, paramType, "p$i", locId, id, i, paramId, isVararg = false, syntheticParameterNames = true, isCrossinline = false, isNoinline = false).also { @@ -975,6 +1174,11 @@ open class KotlinFileExtractor( val methodId = id.cast() extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = extractMethodAndParameterTypeAccesses) addModifiers(id, "static") + if (extReceiver != null) { + val idx = if (dispatchReceiver != null) 1 else 0 + val extendedType = allParamTypeResults[idx] + tw.writeKtExtensionFunctions(methodId, extendedType.javaResult.id, extendedType.kotlinResult.id) + } } tw.writeHasLocation(id, locId) if (f.visibility != DescriptorVisibilities.PRIVATE && f.visibility != DescriptorVisibilities.PRIVATE_TO_THIS) { @@ -1040,8 +1244,8 @@ open class KotlinFileExtractor( val realFnIdxOffset = if (f.extensionReceiverParameter != null) 1 else 0 val paramMappings = f.valueParameters.mapIndexed { idx, param -> Triple(param.type, idx + paramIdxOffset, idx + realFnIdxOffset) } + listOfNotNull( - dispatchReceiver?.let { Triple(it.type, realFnIdxOffset, -1) }, - extReceiver?.let { Triple(it.type, 0, 0) } + dispatchReceiver?.let { Triple(it.type, 0, -1) }, + extReceiver?.let { Triple(it.type, if (dispatchReceiver != null) 1 else 0, 0) } ) paramMappings.forEach { (type, fromIdx, toIdx) -> extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, fromIdx)), type, locId, thisCallId, toIdx, id, returnId) @@ -1077,7 +1281,7 @@ open class KotlinFileExtractor( parentId val sourceDeclId = tw.getLabelFor(getFunctionLabel(f, sourceParentId, listOf(), overloadParameters)) val overriddenAttributes = OverriddenFunctionAttributes(id = overloadId, sourceDeclarationId = sourceDeclId, valueParameters = overloadParameters) - forceExtractFunction(f, parentId, extractBody = false, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = overriddenAttributes) + forceExtractFunction(f, parentId, extractBody = false, extractMethodAndParameterTypeAccesses, extractAnnotations = false, typeSubstitution, classTypeArgsIncludingOuterClasses, overriddenAttributes = overriddenAttributes) tw.writeCompiler_generated(overloadId, CompilerGeneratedKinds.JVMOVERLOADS_METHOD.kind) val realFunctionLocId = tw.getLocation(f) if (extractBody) { @@ -1163,7 +1367,38 @@ open class KotlinFileExtractor( logger.warn("Needed a signature for a type that doesn't have one") } - private fun forceExtractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?, extractOrigin: Boolean = true, overriddenAttributes: OverriddenFunctionAttributes? = null): Label { + private fun getNullabilityAnnotationName(t: IrType, declOrigin: IrDeclarationOrigin, existingAnnotations: List, javaAnnotations: Collection?): FqName? { + if (t !is IrSimpleType) + return null + + fun hasExistingAnnotation(name: FqName) = + existingAnnotations.any { existing -> existing.type.classFqName == name } + + return if (declOrigin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) { + // Java declaration: restore a NotNull or Nullable annotation if the original Java member had one but the Kotlin compiler removed it. + javaAnnotations?.mapNotNull { it.classId?.asSingleFqName() } + ?.singleOrNull { NOT_NULL_ANNOTATIONS.contains(it) || NULLABLE_ANNOTATIONS.contains(it) } + ?.takeUnless { hasExistingAnnotation(it) } + } else { + // Kotlin declaration: add a NotNull annotation to a non-nullable non-primitive type, unless one is already present. + // Usually Kotlin declarations can't have a manual `@NotNull`, but this happens at least when delegating members are + // synthesised and inherit the annotation from the delegate (which given it has @NotNull, is likely written in Java) + JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.takeUnless { t.isNullable() || primitiveTypeMapping.getPrimitiveInfo(t) != null || hasExistingAnnotation(it) } + } + } + + private fun getNullabilityAnnotation(t: IrType, declOrigin: IrDeclarationOrigin, existingAnnotations: List, javaAnnotations: Collection?) = + getNullabilityAnnotationName(t, declOrigin, existingAnnotations, javaAnnotations)?.let { + pluginContext.referenceClass(it)?.let { annotationClass -> + annotationClass.owner.declarations.firstIsInstanceOrNull()?.let { annotationConstructor -> + IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, annotationConstructor.returnType, annotationConstructor.symbol, 0 + ) + } + } + } + + private fun forceExtractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, extractAnnotations: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?, extractOrigin: Boolean = true, overriddenAttributes: OverriddenFunctionAttributes? = null): Label { with("function", f) { DeclarationStackAdjuster(f, overriddenAttributes).use { @@ -1184,6 +1419,7 @@ open class KotlinFileExtractor( id val extReceiver = f.extensionReceiverParameter + // The following parameter order is correct, because member $default methods (where the order would be [dispatchParam], [extensionParam], normalParams) are not extracted here val fParameters = listOfNotNull(extReceiver) + (overriddenAttributes?.valueParameters ?: f.valueParameters) val paramTypes = fParameters.mapIndexed { i, vp -> extractValueParameter(vp, id, i, typeSubstitution, sourceDeclaration, classTypeArgsIncludingOuterClasses, extractTypeAccess = extractMethodAndParameterTypeAccesses, overriddenAttributes?.sourceLoc) @@ -1243,9 +1479,25 @@ open class KotlinFileExtractor( if (f.isSuspend) { addModifiers(id, "suspend") } + if (f.symbol !is IrConstructorSymbol) { + when(overriddenAttributes?.modality ?: (f as? IrSimpleFunction)?.modality) { + Modality.ABSTRACT -> addModifiers(id, "abstract") + Modality.FINAL -> addModifiers(id, "final") + else -> Unit + } + } linesOfCode?.linesOfCodeInDeclaration(f, id) + if (extractAnnotations) { + val extraAnnotations = + if (f.symbol is IrConstructorSymbol) + listOf() + else + listOfNotNull(getNullabilityAnnotation(f.returnType, f.origin, f.annotations, getJavaCallable(f)?.annotations)) + extractAnnotations(f, f.annotations + extraAnnotations, id, extractMethodAndParameterTypeAccesses) + } + return id } } @@ -1257,12 +1509,14 @@ open class KotlinFileExtractor( && f.symbol !is IrConstructorSymbol // not a constructor } - private fun extractField(f: IrField, parentId: Label): Label { + private fun extractField(f: IrField, parentId: Label, extractAnnotationEnumTypeAccesses: Boolean): Label { with("field", f) { DeclarationStackAdjuster(f).use { val fNameSuffix = getExtensionReceiverType(f)?.let { it.classFqName?.asString()?.replace(".", "$$") } ?: "" val extractType = if (isAnnotationClassField(f)) kClassToJavaClass(f.type) else f.type - return extractField(useField(f), "${f.name.asString()}$fNameSuffix", extractType, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal, isDirectlyExposedCompanionObjectField(f)) + val id = useField(f) + extractAnnotations(f, id, extractAnnotationEnumTypeAccesses) + return extractField(id, "${f.name.asString()}$fNameSuffix", extractType, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal, isDirectlyExposedCompanionObjectField(f)) } } } @@ -1294,7 +1548,7 @@ open class KotlinFileExtractor( return id } - private fun extractProperty(p: IrProperty, parentId: Label, extractBackingField: Boolean, extractFunctionBodies: Boolean, extractPrivateMembers: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) { + private fun extractProperty(p: IrProperty, parentId: Label, extractBackingField: Boolean, extractFunctionBodies: Boolean, extractPrivateMembers: Boolean, extractAnnotations: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) { with("property", p) { fun needsInterfaceForwarderQ(f: IrFunction?) = f?.let { needsInterfaceForwarder(f) } ?: false @@ -1316,7 +1570,7 @@ open class KotlinFileExtractor( logger.warnElement("IrProperty without a getter", p) } } else if (shouldExtractDecl(getter, extractPrivateMembers)) { - val getterId = extractFunction(getter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast() + val getterId = extractFunction(getter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = extractAnnotations, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast() if (getterId != null) { tw.writeKtPropertyGetters(id, getterId) if (getter.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR) { @@ -1333,7 +1587,7 @@ open class KotlinFileExtractor( if (!p.isVar) { logger.warnElement("!isVar property with a setter", p) } - val setterId = extractFunction(setter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast() + val setterId = extractFunction(setter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = extractAnnotations, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast() if (setterId != null) { tw.writeKtPropertySetters(id, setterId) if (setter.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR) { @@ -1345,7 +1599,7 @@ open class KotlinFileExtractor( if (bf != null && extractBackingField) { val fieldParentId = useDeclarationParent(getFieldParent(bf), false) if (fieldParentId != null) { - val fieldId = extractField(bf, fieldParentId.cast()) + val fieldId = extractField(bf, fieldParentId.cast(), extractFunctionBodies) tw.writeKtPropertyBackingFields(id, fieldId) if (p.isDelegated) { tw.writeKtPropertyDelegates(id, fieldId) @@ -1355,6 +1609,8 @@ open class KotlinFileExtractor( extractVisibility(p, id, p.visibility) + // TODO: extract annotations + if (p.isLateinit) { addModifiers(id, "lateinit") } @@ -1396,8 +1652,10 @@ open class KotlinFileExtractor( } ee.correspondingClass?.let { - extractDeclaration(it, extractPrivateMembers, extractFunctionBodies) + extractDeclaration(it, extractPrivateMembers, extractFunctionBodies, extractAnnotations = true) } + + extractAnnotations(ee, id, extractFunctionBodies) } } } @@ -1414,6 +1672,8 @@ open class KotlinFileExtractor( val type = useType(ta.expandedType) tw.writeKt_type_alias(id, ta.name.asString(), type.kotlinResult.id) tw.writeHasLocation(id, locId) + + // TODO: extract annotations } } @@ -1767,11 +2027,7 @@ open class KotlinFileExtractor( tw.writeCallableBinding(id, methodLabel) } - private val defaultConstructorMarkerClass by lazy { - val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.DefaultConstructorMarker"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + private val defaultConstructorMarkerClass by lazy { referenceExternalClass("kotlin.jvm.internal.DefaultConstructorMarker") } private val defaultConstructorMarkerType by lazy { defaultConstructorMarkerClass?.typeWith() @@ -1786,11 +2042,12 @@ open class KotlinFileExtractor( ) ?: pluginContext.irBuiltIns.anyType private fun getDefaultsMethodArgTypes(f: IrFunction) = - // The $default method has type ([extensionReceiver], [dispatchReceiver], paramTypes..., int, Object) + // The $default method has type ([dispatchReceiver], [extensionReceiver], paramTypes..., int, Object) // All parameter types are erased. The trailing int is a mask indicating which parameter values are real // and which should be replaced by defaults. The final Object parameter is apparently always null. ( listOfNotNull(if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter?.type) + + listOfNotNull(f.extensionReceiverParameter?.type) + f.valueParameters.map { it.type } + listOf(pluginContext.irBuiltIns.intType, getDefaultsMethodLastArgType(f)) ).map { erase(it) } @@ -1809,17 +2066,16 @@ open class KotlinFileExtractor( private fun getDefaultsMethodLabel(f: IrFunction): Label { val defaultsMethodName = if (f is IrConstructor) "" else getDefaultsMethodName(f) - val normalArgTypes = getDefaultsMethodArgTypes(f) - val extensionParamType = f.extensionReceiverParameter?.let { erase(it.type) } + val argTypes = getDefaultsMethodArgTypes(f) val defaultMethodLabelStr = getFunctionLabel( f.parent, maybeParentId = null, defaultsMethodName, - normalArgTypes, + argTypes, erase(f.returnType), - extensionParamType, - listOf(), + extensionParamType = null, // if there's any, that's included already in argTypes + functionTypeParameters = listOf(), classTypeArgsIncludingOuterClasses = null, overridesCollectionsMethod = false, javaSignature = null, @@ -1879,13 +2135,14 @@ open class KotlinFileExtractor( extensionReceiver: IrExpression? ) { var nextIdx = 0 - if (extensionReceiver != null) { - extractExpressionExpr(extensionReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) - } if (dispatchReceiver != null && !callTarget.shouldExtractAsStatic) { extractExpressionExpr(dispatchReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) } + if (extensionReceiver != null) { + extractExpressionExpr(extensionReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) + } + val valueArgsWithDummies = valueArguments.zip(callTarget.valueParameters).map { (expr, param) -> expr ?: IrConstImpl.defaultValueForType(0, 0, param.type) } @@ -2088,7 +2345,7 @@ open class KotlinFileExtractor( extractValueArguments(argParent, idxOffset) } - private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { + private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label, locId: Label, enclosingCallable: Label?, enclosingStmt: Label?) { if (parent is IrClass) { extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt) } else if (parent is IrFile) { @@ -2098,7 +2355,7 @@ open class KotlinFileExtractor( } } - private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { + private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label, locId: Label, enclosingCallable: Label?, enclosingStmt: Label?) { if (target.shouldExtractAsStatic) { extractStaticTypeAccessQualifierUnchecked(target.parent, parentExpr, locId, enclosingCallable, enclosingStmt) } @@ -2133,11 +2390,7 @@ open class KotlinFileExtractor( private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType { it.name.asString() == name } - val jvmIntrinsicsClass by lazy { - val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val jvmIntrinsicsClass by lazy { referenceExternalClass("kotlin.jvm.internal.Intrinsics") } private fun findJdkIntrinsicOrWarn(name: String, warnAgainstElement: IrElement): IrFunction? { val result = jvmIntrinsicsClass?.let { findFunction(it, name) } @@ -2183,11 +2436,7 @@ open class KotlinFileExtractor( return prop } - val javaLangString by lazy { - val result = pluginContext.referenceClass(FqName("java.lang.String"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val javaLangString by lazy { referenceExternalClass("java.lang.String") } val stringValueOfObjectMethod by lazy { val result = javaLangString?.declarations?.findSubType { @@ -2211,11 +2460,7 @@ open class KotlinFileExtractor( result } - val kotlinNoWhenBranchMatchedExn by lazy { - val result = pluginContext.referenceClass(FqName("kotlin.NoWhenBranchMatchedException"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val kotlinNoWhenBranchMatchedExn by lazy {referenceExternalClass("kotlin.NoWhenBranchMatchedException") } val kotlinNoWhenBranchMatchedConstructor by lazy { val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType { @@ -2227,11 +2472,7 @@ open class KotlinFileExtractor( result } - val javaUtilArrays by lazy { - val result = pluginContext.referenceClass(FqName("java.util.Arrays"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val javaUtilArrays by lazy { referenceExternalClass("java.util.Arrays") } private fun isFunction(target: IrFunction, pkgName: String, classNameLogged: String, classNamePredicate: (String) -> Boolean, vararg fNames: String, isNullable: Boolean? = false) = fNames.any { isFunction(target, pkgName, classNameLogged, classNamePredicate, it, isNullable) } @@ -3379,10 +3620,10 @@ open class KotlinFileExtractor( extractExpression(e, callable, ExprParent(parent, idx, enclosingStmt)) } - private fun extractExprContext(id: Label, locId: Label, callable: Label, enclosingStmt: Label) { + private fun extractExprContext(id: Label, locId: Label, callable: Label?, enclosingStmt: Label?) { tw.writeHasLocation(id, locId) - tw.writeCallableEnclosingExpr(id, callable) - tw.writeStatementEnclosingExpr(id, enclosingStmt) + callable?.let { tw.writeCallableEnclosingExpr(id, it) } + enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) } } private fun extractEqualsExpression(locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = @@ -3401,8 +3642,8 @@ open class KotlinFileExtractor( extractExprContext(it, locId, callable, enclosingStmt) } - private fun extractConstantInteger(v: Number, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = - tw.getFreshIdLabel().also { + private fun extractConstantInteger(v: Number, locId: Label, parent: Label, idx: Int, callable: Label?, enclosingStmt: Label?, overrideId: Label? = null) = + exprIdOrFresh(overrideId).also { val type = useType(pluginContext.irBuiltIns.intType) tw.writeExprs_integerliteral(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) @@ -3410,8 +3651,8 @@ open class KotlinFileExtractor( extractExprContext(it, locId, callable, enclosingStmt) } - private fun extractNull(t: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = - tw.getFreshIdLabel().also { + private fun extractNull(t: IrType, locId: Label, parent: Label, idx: Int, callable: Label?, enclosingStmt: Label?, overrideId: Label? = null) = + exprIdOrFresh(overrideId).also { val type = useType(t) tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) @@ -3426,23 +3667,6 @@ open class KotlinFileExtractor( extractExprContext(it, locId, callable, enclosingStmt) } - private fun escapeCharForQuotedLiteral(c: Char) = - when (c) { - '\r' -> "\\r" - '\n' -> "\\n" - '\t' -> "\\t" - '\\' -> "\\\\" - '"' -> "\\\"" - else -> c.toString() - } - - // Render a string literal as it might occur in Kotlin source. Note this is a reasonable guess; the real source - // could use other escape sequences to describe the same String. Importantly, this is the same guess the Java - // extractor makes regarding string literals occurring within annotations, which we need to coincide with to ensure - // database consistency. - private fun toQuotedLiteral(s: String) = - s.toCharArray().joinToString(separator = "", prefix = "\"", postfix = "\"") { c -> escapeCharForQuotedLiteral(c) } - private fun extractExpression(e: IrExpression, callable: Label, parent: StmtExprParent) { with("expression", e) { when(e) { @@ -3593,72 +3817,7 @@ open class KotlinFileExtractor( } is IrConst<*> -> { val exprParent = parent.expr(e, callable) - val v = e.value - when { - v is Number && (v is Int || v is Short || v is Byte) -> { - extractConstantInteger(v, tw.getLocation(e), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) - } - v is Long -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_longliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(v.toString(), v.toString(), id) - } - v is Float -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_floatingpointliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(v.toString(), v.toString(), id) - } - v is Double -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_doubleliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(v.toString(), v.toString(), id) - } - v is Boolean -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_booleanliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(v.toString(), v.toString(), id) - } - v is Char -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_characterliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(v.toString(), v.toString(), id) - } - v is String -> { - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_stringliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - tw.writeNamestrings(toQuotedLiteral(v.toString()), v.toString(), id) - } - v == null -> { - extractNull(e.type, tw.getLocation(e), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) - } - else -> { - logger.errorElement("Unrecognised IrConst: " + v.javaClass, e) - } - } + extractConstant(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrGetValue -> { val exprParent = parent.expr(e, callable) @@ -3687,19 +3846,7 @@ open class KotlinFileExtractor( } is IrGetEnumValue -> { val exprParent = parent.expr(e, callable) - val id = tw.getFreshIdLabel() - val type = useType(e.type) - val locId = tw.getLocation(e) - tw.writeExprs_varaccess(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - - val owner = getBoundSymbolOwner(e.symbol, e) ?: return - - val vId = useEnumEntry(owner) - tw.writeVariableBinding(id, vId) - - extractStaticTypeAccessQualifier(owner, id, locId, callable, exprParent.enclosingStmt) + extractEnumValue(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrSetValue, is IrSetField -> { @@ -3943,14 +4090,7 @@ open class KotlinFileExtractor( } is IrClassReference -> { val exprParent = parent.expr(e, callable) - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(e) - val type = useType(e.type) - tw.writeExprs_typeliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - extractExprContext(id, locId, callable, exprParent.enclosingStmt) - - extractTypeAccessRecursive(e.classType, locId, id, 0, callable, exprParent.enclosingStmt) + extractClassReference(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrPropertyReference -> { extractPropertyReference("property reference", e, e.getter, e.setter, e.field, parent, callable) @@ -4039,8 +4179,7 @@ open class KotlinFileExtractor( // Use of 'this' in a function where the dispatch receiver is passed like an ordinary parameter, // such as a `$default` static function that substitutes in default arguments as needed. val paramDeclarerId = overriddenAttributes.id ?: useDeclarationParent(thisParamParent, false) - val extensionParamOffset = if (thisParamParent.extensionReceiverParameter != null) 1 else 0 - val replacementParamId = tw.getLabelFor(getValueParameterLabel(paramDeclarerId, replaceWithParamIdx + extensionParamOffset)) + val replacementParamId = tw.getLabelFor(getValueParameterLabel(paramDeclarerId, replaceWithParamIdx)) extractVariableAccess(replacementParamId, e.type, locId, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) return } @@ -4149,6 +4288,158 @@ open class KotlinFileExtractor( extractExpressionExpr(loop.condition, callable, id, 0, id) } + private fun exprIdOrFresh(id: Label?) = id?.cast() ?: tw.getFreshIdLabel() + + private fun extractClassReference( + e: IrClassReference, + parent: Label, + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label?, + overrideId: Label? = null, + typeAccessOverrideId: Label? = null, + useJavaLangClassType: Boolean = false + ) = + exprIdOrFresh(overrideId).also { id -> + val locId = tw.getLocation(e) + val jlcType = if (useJavaLangClassType) this.javaLangClass?.let { it.typeWith() } else null + val type = useType(jlcType ?: e.type) + tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + + extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt, overrideId = typeAccessOverrideId) + } + + private fun extractEnumValue( + e: IrGetEnumValue, + parent: Label, + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label?, + extractTypeAccess: Boolean = true, + overrideId: Label? = null + ) = + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_varaccess(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + + getBoundSymbolOwner(e.symbol, e)?.let { owner -> + + val vId = useEnumEntry(owner) + tw.writeVariableBinding(id, vId) + + if (extractTypeAccess) + extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) + + } + } + + private fun escapeCharForQuotedLiteral(c: Char) = + when(c) { + '\r' -> "\\r" + '\n' -> "\\n" + '\t' -> "\\t" + '\\' -> "\\\\" + '"' -> "\\\"" + else -> c.toString() + } + + // Render a string literal as it might occur in Kotlin source. Note this is a reasonable guess; the real source + // could use other escape sequences to describe the same String. Importantly, this is the same guess the Java + // extractor makes regarding string literals occurring within annotations, which we need to coincide with to ensure + // database consistency. + private fun toQuotedLiteral(s: String) = + s.toCharArray().joinToString(separator = "", prefix = "\"", postfix = "\"") { c -> escapeCharForQuotedLiteral(c) } + + private fun extractConstant( + e: IrConst<*>, + parent: Label, + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label?, + overrideId: Label? = null + ): Label? { + + val v = e.value + return when { + v is Number && (v is Int || v is Short || v is Byte) -> { + extractConstantInteger(v, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId) + } + v is Long -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_longliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(v.toString(), v.toString(), id) + } + } + v is Float -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_floatingpointliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(v.toString(), v.toString(), id) + } + } + v is Double -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_doubleliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(v.toString(), v.toString(), id) + } + } + v is Boolean -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_booleanliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(v.toString(), v.toString(), id) + } + } + v is Char -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_characterliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(v.toString(), v.toString(), id) + } + } + v is String -> { + exprIdOrFresh(overrideId).also { id -> + val type = useType(e.type) + val locId = tw.getLocation(e) + tw.writeExprs_stringliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) + tw.writeNamestrings(toQuotedLiteral(v.toString()), v.toString(), id) + } + } + v == null -> { + extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId) + } + else -> { + null.also { + logger.errorElement("Unrecognised IrConst: " + v.javaClass, e) + } + } + } + } + private fun IrValueParameter.isExtensionReceiver(): Boolean { val parentFun = parent as? IrFunction ?: return false return parentFun.extensionReceiverParameter == this @@ -4441,6 +4732,8 @@ open class KotlinFileExtractor( } } + private val propertyRefType by lazy { referenceExternalClass("kotlin.jvm.internal.PropertyReference")?.typeWith() } + private fun extractPropertyReference( exprKind: String, propertyReferenceExpr: IrCallableReference, @@ -4504,8 +4797,7 @@ open class KotlinFileExtractor( val declarationParent = peekDeclStackAsDeclarationParent(propertyReferenceExpr) ?: return // The base class could be `Any`. `PropertyReference` is used to keep symmetry with function references. - val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.PropertyReference"))?.owner?.typeWith() - ?: pluginContext.irBuiltIns.anyType + val baseClass = propertyRefType ?: pluginContext.irBuiltIns.anyType val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, propertyReferenceExpr, declarationParent) @@ -4599,6 +4891,8 @@ open class KotlinFileExtractor( } } + private val functionRefType by lazy { referenceExternalClass("kotlin.jvm.internal.FunctionReference")?.typeWith() } + private fun extractFunctionReference( functionReferenceExpr: IrFunctionReference, parent: StmtExprParent, @@ -4713,8 +5007,7 @@ open class KotlinFileExtractor( } else { val declarationParent = peekDeclStackAsDeclarationParent(functionReferenceExpr) ?: return // `FunctionReference` base class is required, because that's implementing `KFunction`. - val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.FunctionReference"))?.owner?.typeWith() - ?: pluginContext.irBuiltIns.anyType + val baseClass = functionRefType ?: pluginContext.irBuiltIns.anyType val classId = extractGeneratedClass(ids, listOf(baseClass, fnInterfaceType), locId, functionReferenceExpr, declarationParent, null, { it.valueParameters.size == 1 }) { // The argument to FunctionReference's constructor is the function arity. @@ -4760,34 +5053,14 @@ open class KotlinFileExtractor( } } - private fun getFunctionalInterfaceType(functionNTypeArguments: List): IrSimpleType? { - if (functionNTypeArguments.size > BuiltInFunctionArity.BIG_ARITY) { - val funName = "kotlin.jvm.functions.FunctionN" - val theFun = pluginContext.referenceClass(FqName(funName)) - if (theFun == null) { - logger.warn("Cannot find $funName for getFunctionalInterfaceType") - return null - } else { - return theFun.typeWith(functionNTypeArguments.last()) - } - } else { - return functionN(pluginContext)(functionNTypeArguments.size - 1).typeWith(functionNTypeArguments) - } - } + private fun getFunctionalInterfaceType(functionNTypeArguments: List) = + getFunctionalInterfaceTypeWithTypeArgs(functionNTypeArguments.map { makeTypeProjection(it, Variance.INVARIANT) }) - private fun getFunctionalInterfaceTypeWithTypeArgs(functionNTypeArguments: List): IrSimpleType? = - if (functionNTypeArguments.size > BuiltInFunctionArity.BIG_ARITY) { - val funName = "kotlin.jvm.functions.FunctionN" - val theFun = pluginContext.referenceClass(FqName(funName)) - if (theFun == null) { - logger.warn("Cannot find $funName for getFunctionalInterfaceTypeWithTypeArgs") - null - } else { - theFun.typeWithArguments(listOf(functionNTypeArguments.last())) - } - } else { + private fun getFunctionalInterfaceTypeWithTypeArgs(functionNTypeArguments: List) = + if (functionNTypeArguments.size > BuiltInFunctionArity.BIG_ARITY) + referenceExternalClass("kotlin.jvm.functions.FunctionN")?.symbol?.typeWithArguments(listOf(functionNTypeArguments.last())) + else functionN(pluginContext)(functionNTypeArguments.size - 1).symbol.typeWithArguments(functionNTypeArguments) - } private data class FunctionLabels( val methodId: Label, @@ -4993,11 +5266,11 @@ open class KotlinFileExtractor( /** * Extracts a single type access expression with no enclosing callable and statement. */ - private fun extractTypeAccess(type: TypeResults, location: Label, parent: Label, idx: Int): Label { + private fun extractTypeAccess(type: TypeResults, location: Label, parent: Label, idx: Int, overrideId: Label? = null): Label { // TODO: elementForLocation allows us to give some sort of // location, but a proper location for the type access will // require upstream changes - val id = tw.getFreshIdLabel() + val id = exprIdOrFresh(overrideId) tw.writeExprs_unannotatedtypeaccess(id, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(id, type.kotlinResult.id) tw.writeHasLocation(id, location) @@ -5007,10 +5280,14 @@ open class KotlinFileExtractor( /** * Extracts a single type access expression with enclosing callable and statement. */ - private fun extractTypeAccess(type: TypeResults, location: Label, parent: Label, idx: Int, enclosingCallable: Label, enclosingStmt: Label): Label { - val id = extractTypeAccess(type, location, parent, idx) - tw.writeCallableEnclosingExpr(id, enclosingCallable) - tw.writeStatementEnclosingExpr(id, enclosingStmt) + private fun extractTypeAccess(type: TypeResults, location: Label, parent: Label, idx: Int, enclosingCallable: Label?, enclosingStmt: Label?, overrideId: Label? = null): Label { + val id = extractTypeAccess(type, location, parent, idx, overrideId = overrideId) + if (enclosingCallable != null) { + tw.writeCallableEnclosingExpr(id, enclosingCallable) + } + if (enclosingStmt != null) { + tw.writeStatementEnclosingExpr(id, enclosingStmt) + } return id } @@ -5052,11 +5329,14 @@ open class KotlinFileExtractor( /** * Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled. */ - private fun extractTypeAccessRecursive(t: IrType, location: Label, parent: Label, idx: Int, enclosingCallable: Label, enclosingStmt: Label, typeContext: TypeContext = TypeContext.OTHER): Label { + private fun extractTypeAccessRecursive(t: IrType, location: Label, parent: Label, idx: Int, enclosingCallable: Label?, enclosingStmt: Label?, typeContext: TypeContext = TypeContext.OTHER, overrideId: Label? = null): Label { // TODO: `useType` substitutes types to their java equivalent, and sometimes that also means changing the number of type arguments. The below logic doesn't take this into account. // For example `KFunction2` becomes `KFunction` with three child type access expressions: `Int`, `Double`, `String`. - val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt) + val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId) if (t is IrSimpleType) { + if (t.arguments.isNotEmpty() && overrideId != null) { + logger.error("Unexpected parameterized type with an overridden expression ID; children will be assigned fresh IDs") + } extractTypeArguments(t.arguments.filterIsInstance(), location, typeAccessId, enclosingCallable, enclosingStmt) } return typeAccessId @@ -5070,8 +5350,8 @@ open class KotlinFileExtractor( typeArgs: List, location: Label, parentExpr: Label, - enclosingCallable: Label, - enclosingStmt: Label, + enclosingCallable: Label?, + enclosingStmt: Label?, startIndex: Int = 0, reverse: Boolean = false ) { @@ -5304,7 +5584,7 @@ open class KotlinFileExtractor( // we would need to compose generic type substitutions -- for example, if we're implementing // T UnaryOperator.apply(T t) here, we would need to compose substitutions so we can implement // the real underlying R Function.apply(T t). - forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, overriddenAttributes = OverriddenFunctionAttributes(id = ids.function, sourceLoc = tw.getLocation(e))) + forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, extractAnnotations = false, typeSub, classTypeArgs, overriddenAttributes = OverriddenFunctionAttributes(id = ids.function, sourceLoc = tw.getLocation(e), modality = Modality.FINAL)) addModifiers(ids.function, "override") if (st.isSuspendFunctionOrKFunction()) { @@ -5486,7 +5766,7 @@ open class KotlinFileExtractor( val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction, localFunction.parent, compilerGeneratedKindOverride = compilerGeneratedKindOverride) // Extract local function as a member - extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, null, listOf()) + extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, extractAnnotations = false, null, listOf()) return id } @@ -5529,6 +5809,7 @@ open class KotlinFileExtractor( val typeParameters: List? = null, val isStatic: Boolean? = null, val visibility: DescriptorVisibility? = null, + val modality: Modality? = null, ) private fun peekDeclStackAsDeclarationParent(elementToReportOn: IrElement): IrDeclarationParent? { diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index dbacf42a192..cc335d3f8cb 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -40,11 +40,15 @@ open class KotlinUsesExtractor( val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState ) { - val javaLangObject by lazy { - val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + fun referenceExternalClass(name: String) = + pluginContext.referenceClass(FqName(name))?.owner.also { + if (it == null) + logger.warn("Unable to resolve external class $name") + else + extractExternalClassLater(it) + } + + val javaLangObject by lazy { referenceExternalClass("java.lang.Object") } val javaLangObjectType by lazy { javaLangObject?.typeWith() @@ -885,11 +889,7 @@ open class KotlinUsesExtractor( else -> null } - val javaUtilCollection by lazy { - val result = pluginContext.referenceClass(FqName("java.util.Collection"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val javaUtilCollection by lazy { referenceExternalClass("java.util.Collection") } val wildcardCollectionType by lazy { javaUtilCollection?.let { @@ -1152,11 +1152,7 @@ open class KotlinUsesExtractor( return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\"" } - val javaLangClass by lazy { - val result = pluginContext.referenceClass(FqName("java.lang.Class"))?.owner - result?.let { extractExternalClassLater(it) } - result - } + val javaLangClass by lazy { referenceExternalClass("java.lang.Class") } fun kClassToJavaClass(t: IrType): IrType { when(t) { diff --git a/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt b/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt new file mode 100644 index 00000000000..5fdf073813d --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt @@ -0,0 +1,396 @@ +package com.github.codeql + +import com.github.codeql.utils.versions.copyParameterToFunction +import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor +import com.github.codeql.utils.versions.getAnnotationType +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.addConstructor +import org.jetbrains.kotlin.ir.builders.declarations.addGetter +import org.jetbrains.kotlin.ir.builders.declarations.addProperty +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.builders.declarations.buildField +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrEnumEntry +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue +import org.jetbrains.kotlin.ir.expressions.IrVararg +import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.constructedClass +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.ir.util.getAnnotation +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.ir.util.hasEqualFqName +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.primaryConstructor +import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import java.lang.annotation.ElementType +import java.util.HashSet + +class MetaAnnotationSupport(private val logger: FileLogger, private val pluginContext: IrPluginContext, private val extractor: KotlinFileExtractor) { + + // Taken from AdditionalIrUtils.kt (not available in Kotlin < 1.6) + private val IrConstructorCall.annotationClass + get() = this.symbol.owner.constructedClass + + // Taken from AdditionalIrUtils.kt (not available in Kotlin < 1.6) + private fun IrConstructorCall.isAnnotationWithEqualFqName(fqName: FqName): Boolean = + annotationClass.hasEqualFqName(fqName) + + // Adapted from RepeatedAnnotationLowering.kt + fun groupRepeatableAnnotations(annotations: List): List { + if (annotations.size < 2) return annotations + + val annotationsByClass = annotations.groupByTo(mutableMapOf()) { it.annotationClass } + if (annotationsByClass.values.none { it.size > 1 }) return annotations + + val result = mutableListOf() + for (annotation in annotations) { + val annotationClass = annotation.annotationClass + val grouped = annotationsByClass.remove(annotationClass) ?: continue + if (grouped.size < 2) { + result.add(grouped.single()) + continue + } + + val containerClass = getOrCreateContainerClass(annotationClass) + if (containerClass != null) + wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)?.let { + result.add(it) + } + else + logger.warnElement("Failed to find an annotation container class", annotationClass) + } + return result + } + + // Adapted from RepeatedAnnotationLowering.kt + private fun getOrCreateContainerClass(annotationClass: IrClass): IrClass? { + val metaAnnotations = annotationClass.annotations + val jvmRepeatable = metaAnnotations.find { it.symbol.owner.parentAsClass.fqNameWhenAvailable == JvmAnnotationNames.REPEATABLE_ANNOTATION } + return if (jvmRepeatable != null) { + ((jvmRepeatable.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol)?.owner + } else { + getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass) + } + } + + // Adapted from RepeatedAnnotationLowering.kt + private fun wrapAnnotationEntriesInContainer( + annotationClass: IrClass, + containerClass: IrClass, + entries: List + ): IrConstructorCall? { + val annotationType = annotationClass.typeWith() + val containerConstructor = containerClass.primaryConstructor + if (containerConstructor == null) { + logger.warnElement("Expected container class to have a primary constructor", containerClass) + return null + } else { + return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerConstructor.symbol).apply { + putValueArgument( + 0, + IrVarargImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + pluginContext.irBuiltIns.arrayClass.typeWith(annotationType), + annotationType, + entries + ) + ) + } + } + } + + // Taken from AdditionalClassAnnotationLowering.kt + private fun getApplicableTargetSet(c: IrClass): Set? { + val targetEntry = c.getAnnotation(StandardNames.FqNames.target) ?: return null + return loadAnnotationTargets(targetEntry) + } + + // Taken from AdditionalClassAnnotationLowering.kt + private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set? { + val valueArgument = targetEntry.getValueArgument(0) as? IrVararg ?: return null + return valueArgument.elements.filterIsInstance().mapNotNull { + KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) + }.toSet() + } + + private val javaAnnotationTargetElementType by lazy { extractor.referenceExternalClass("java.lang.annotation.ElementType") } + + private val javaAnnotationTarget by lazy { extractor.referenceExternalClass("java.lang.annotation.Target") } + + private fun findEnumEntry(c: IrClass, name: String) = + c.declarations.filterIsInstance().find { it.name.asString() == name } + + // Adapted from JvmSymbols.kt + private val jvm6TargetMap by lazy { + javaAnnotationTargetElementType?.let { + val etMethod = findEnumEntry(it, "METHOD") + mapOf( + KotlinTarget.CLASS to findEnumEntry(it, "TYPE"), + KotlinTarget.ANNOTATION_CLASS to findEnumEntry(it, "ANNOTATION_TYPE"), + KotlinTarget.CONSTRUCTOR to findEnumEntry(it, "CONSTRUCTOR"), + KotlinTarget.LOCAL_VARIABLE to findEnumEntry(it, "LOCAL_VARIABLE"), + KotlinTarget.FUNCTION to etMethod, + KotlinTarget.PROPERTY_GETTER to etMethod, + KotlinTarget.PROPERTY_SETTER to etMethod, + KotlinTarget.FIELD to findEnumEntry(it, "FIELD"), + KotlinTarget.VALUE_PARAMETER to findEnumEntry(it, "PARAMETER") + ) + } + } + + // Adapted from JvmSymbols.kt + private val jvm8TargetMap by lazy { + javaAnnotationTargetElementType?.let { + jvm6TargetMap?.let { j6Map -> + j6Map + mapOf( + KotlinTarget.TYPE_PARAMETER to findEnumEntry(it, "TYPE_PARAMETER"), + KotlinTarget.TYPE to findEnumEntry(it, "TYPE_USE") + ) + } + } + } + + private fun getAnnotationTargetMap() = + if (pluginContext.platform?.any { it.targetPlatformVersion == JvmTarget.JVM_1_6 } == true) + jvm6TargetMap + else + jvm8TargetMap + + // Adapted from AdditionalClassAnnotationLowering.kt + private fun generateTargetAnnotation(c: IrClass): IrConstructorCall? { + if (c.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION)) + return null + val elementType = javaAnnotationTargetElementType ?: return null + val targetType = javaAnnotationTarget ?: return null + val targetConstructor = targetType.declarations.firstIsInstanceOrNull() ?: return null + val targets = getApplicableTargetSet(c) ?: return null + val annotationTargetMap = getAnnotationTargetMap() ?: return null + + val javaTargets = targets.mapNotNullTo(HashSet()) { annotationTargetMap[it] }.sortedBy { + ElementType.valueOf(it.symbol.owner.name.asString()) + } + val vararg = IrVarargImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + type = pluginContext.irBuiltIns.arrayClass.typeWith(elementType.defaultType), + varargElementType = elementType.defaultType + ) + for (target in javaTargets) { + vararg.elements.add( + IrGetEnumValueImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, elementType.defaultType, target.symbol + ) + ) + } + + return IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0 + ).apply { + putValueArgument(0, vararg) + } + } + + private val javaAnnotationRetention by lazy { extractor.referenceExternalClass("java.lang.annotation.Retention") } + private val javaAnnotationRetentionPolicy by lazy { extractor.referenceExternalClass("java.lang.annotation.RetentionPolicy") } + private val javaAnnotationRetentionPolicyRuntime by lazy { javaAnnotationRetentionPolicy?.let { findEnumEntry(it, "RUNTIME") } } + + private val annotationRetentionMap by lazy { + javaAnnotationRetentionPolicy?.let { + mapOf( + KotlinRetention.SOURCE to findEnumEntry(it, "SOURCE"), + KotlinRetention.BINARY to findEnumEntry(it, "CLASS"), + KotlinRetention.RUNTIME to javaAnnotationRetentionPolicyRuntime + ) + } + } + + // Taken from AnnotationCodegen.kt (not available in Kotlin < 1.6.20) + private fun IrClass.getAnnotationRetention(): KotlinRetention? { + val retentionArgument = + getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(0) + as? IrGetEnumValue ?: return null + val retentionArgumentValue = retentionArgument.symbol.owner + return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) + } + + // Taken from AdditionalClassAnnotationLowering.kt + private fun generateRetentionAnnotation(irClass: IrClass): IrConstructorCall? { + if (irClass.hasAnnotation(JvmAnnotationNames.RETENTION_ANNOTATION)) + return null + val retentionMap = annotationRetentionMap ?: return null + val kotlinRetentionPolicy = irClass.getAnnotationRetention() + val javaRetentionPolicy = kotlinRetentionPolicy?.let { retentionMap[it] } ?: javaAnnotationRetentionPolicyRuntime ?: return null + val retentionPolicyType = javaAnnotationRetentionPolicy ?: return null + val retentionType = javaAnnotationRetention ?: return null + val targetConstructor = retentionType.declarations.firstIsInstanceOrNull() ?: return null + + return IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0 + ).apply { + putValueArgument( + 0, + IrGetEnumValueImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionPolicyType.defaultType, javaRetentionPolicy.symbol + ) + ) + } + } + + private val javaAnnotationRepeatable by lazy { extractor.referenceExternalClass("java.lang.annotation.Repeatable") } + private val kotlinAnnotationRepeatableContainer by lazy { extractor.referenceExternalClass("kotlin.jvm.internal.RepeatableContainer") } + + // Taken from declarationBuilders.kt (not available in Kotlin < 1.6): + private fun addDefaultGetter(p: IrProperty, parentClass: IrClass) { + val field = p.backingField ?: + run { logger.warnElement("Expected property to have a backing field", p); return } + p.addGetter { + origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + returnType = field.type + }.apply { + val thisReceiever = parentClass.thisReceiver ?: + run { logger.warnElement("Expected property's parent class to have a receiver parameter", parentClass); return } + val newParam = copyParameterToFunction(thisReceiever, this) + dispatchReceiverParameter = newParam + body = factory.createBlockBody( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf( + IrReturnImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + pluginContext.irBuiltIns.nothingType, + symbol, + IrGetFieldImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + field.symbol, + field.type, + IrGetValueImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + newParam.type, + newParam.symbol + ) + ) + ) + ) + ) + } + } + + // Taken from JvmCachedDeclarations.kt + private fun getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass: IrClass) = + extractor.globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(annotationClass) { + val containerClass = pluginContext.irFactory.buildClass { + kind = ClassKind.ANNOTATION_CLASS + name = Name.identifier("Container") + }.apply { + createImplicitParameterDeclarationWithWrappedDescriptor() + parent = annotationClass + superTypes = listOf(getAnnotationType(pluginContext)) + } + + val propertyName = Name.identifier("value") + val propertyType = pluginContext.irBuiltIns.arrayClass.typeWith(annotationClass.typeWith()) + + containerClass.addConstructor { + isPrimary = true + }.apply { + addValueParameter(propertyName.identifier, propertyType) + } + + containerClass.addProperty { + name = propertyName + }.apply property@{ + backingField = pluginContext.irFactory.buildField { + name = propertyName + type = propertyType + }.apply { + parent = containerClass + correspondingPropertySymbol = this@property.symbol + } + addDefaultGetter(this, containerClass) + } + + val repeatableContainerAnnotation = kotlinAnnotationRepeatableContainer?.constructors?.single() + + containerClass.annotations = annotationClass.annotations + .filter { + it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) || + it.isAnnotationWithEqualFqName(StandardNames.FqNames.target) + } + .map { it.deepCopyWithSymbols(containerClass) } + + listOfNotNull( + repeatableContainerAnnotation?.let { + IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.returnType, it.symbol, 0 + ) + } + ) + + containerClass + } + + // Adapted from AdditionalClassAnnotationLowering.kt + private fun generateRepeatableAnnotation(irClass: IrClass, extractAnnotationTypeAccesses: Boolean): IrConstructorCall? { + if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) || + irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) + ) return null + + val repeatableConstructor = javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull() ?: return null + + val containerClass = getOrCreateSyntheticRepeatableAnnotationContainer(irClass) + // Whenever a repeatable annotation with a Kotlin-synthesised container is extracted, extract the synthetic container to the same trap file. + extractor.extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = extractAnnotationTypeAccesses) + + val containerReference = IrClassReferenceImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType), + containerClass.symbol, containerClass.defaultType + ) + return IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, repeatableConstructor.returnType, repeatableConstructor.symbol, 0 + ).apply { + putValueArgument(0, containerReference) + } + } + + private val javaAnnotationDocumented by lazy { extractor.referenceExternalClass("java.lang.annotation.Documented") } + + // Taken from AdditionalClassAnnotationLowering.kt + private fun generateDocumentedAnnotation(irClass: IrClass): IrConstructorCall? { + if (!irClass.hasAnnotation(StandardNames.FqNames.mustBeDocumented) || + irClass.hasAnnotation(JvmAnnotationNames.DOCUMENTED_ANNOTATION) + ) return null + + val documentedConstructor = javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull() ?: return null + + return IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol, 0 + ) + } + + fun generateJavaMetaAnnotations(c: IrClass, extractAnnotationTypeAccesses: Boolean) = + // This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend. + listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c, extractAnnotationTypeAccesses), generateDocumentedAnnotation(c)) +} + diff --git a/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt b/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt index 36ebda9dd1c..3b66e527429 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/Logger.kt @@ -10,7 +10,7 @@ import java.util.Stack import org.jetbrains.kotlin.ir.IrElement class LogCounter() { - public val diagnosticCounts = mutableMapOf() + public val diagnosticInfo = mutableMapOf>() public val diagnosticLimit: Int init { diagnosticLimit = System.getenv("CODEQL_EXTRACTOR_KOTLIN_DIAGNOSTIC_LIMIT")?.toIntOrNull() ?: 100 @@ -114,12 +114,23 @@ open class LoggerBase(val logCounter: LogCounter) { if(diagnosticLoc == null) { " Missing caller information.\n" } else { - val count = logCounter.diagnosticCounts.getOrDefault(diagnosticLoc, 0) + 1 - logCounter.diagnosticCounts[diagnosticLoc] = count + val oldInfo = logCounter.diagnosticInfo.getOrDefault(diagnosticLoc, Pair(severity, 0)) + if(severity != oldInfo.first) { + // We don't want to get in a loop, so just emit this + // directly without going through the diagnostic + // counting machinery + if (verbosity >= 1) { + val message = "Severity mismatch ($severity vs ${oldInfo.first}) at $diagnosticLoc" + emitDiagnostic(tw, Severity.Error, "Inconsistency", message, message) + } + } + val newCount = oldInfo.second + 1 + val newInfo = Pair(severity, newCount) + logCounter.diagnosticInfo[diagnosticLoc] = newInfo when { logCounter.diagnosticLimit <= 0 -> "" - count == logCounter.diagnosticLimit -> " Limit reached for diagnostics from $diagnosticLoc.\n" - count > logCounter.diagnosticLimit -> return + newCount == logCounter.diagnosticLimit -> " Limit reached for diagnostics from $diagnosticLoc.\n" + newCount > logCounter.diagnosticLimit -> return else -> "" } } @@ -189,14 +200,16 @@ open class LoggerBase(val logCounter: LogCounter) { } fun printLimitedDiagnosticCounts(tw: TrapWriter) { - for((caller, count) in logCounter.diagnosticCounts) { + for((caller, info) in logCounter.diagnosticInfo) { + val severity = info.first + val count = info.second if(count >= logCounter.diagnosticLimit) { // We don't know if this location relates to an error // or a warning, so we just declare hitting the limit // to be an error regardless. val message = "Total of $count diagnostics (reached limit of ${logCounter.diagnosticLimit}) from $caller." if (verbosity >= 1) { - emitDiagnostic(tw, Severity.Error, "Limit", message, message) + emitDiagnostic(tw, severity, "Limit", message, message) } } } diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/annotationType.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/annotationType.kt new file mode 100644 index 00000000000..08fd0315f7c --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/annotationType.kt @@ -0,0 +1,8 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI + +@OptIn(ObsoleteDescriptorBasedAPI::class) +fun getAnnotationType(context: IrPluginContext) = + context.typeTranslator.translateType(context.builtIns.annotationType) \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/copyTo.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/copyTo.kt new file mode 100644 index 00000000000..4147daa340f --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/copyTo.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.backend.common.ir.copyTo + +fun copyParameterToFunction(p: IrValueParameter, f: IrFunction) = p.copyTo(f) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/annotationType.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/annotationType.kt new file mode 100644 index 00000000000..3ce3cad89ec --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/annotationType.kt @@ -0,0 +1,6 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext + +fun getAnnotationType(context: IrPluginContext) = + context.irBuiltIns.annotationType \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_7_20/copyTo.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_7_20/copyTo.kt new file mode 100644 index 00000000000..701bd21036e --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_7_20/copyTo.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.util.copyTo + +fun copyParameterToFunction(p: IrValueParameter, f: IrFunction) = p.copyTo(f) \ No newline at end of file diff --git a/java/ql/consistency-queries/cfgDeadEnds.ql b/java/ql/consistency-queries/cfgDeadEnds.ql index c0f2e6cfe1f..b2ad4b08f6b 100644 --- a/java/ql/consistency-queries/cfgDeadEnds.ql +++ b/java/ql/consistency-queries/cfgDeadEnds.ql @@ -53,6 +53,8 @@ predicate shouldBeDeadEnd(ControlFlowNode n) { not exists(n.getFile().getRelativePath()) // TODO or n = any(ConstCase c).getValue(_) // TODO + or + n instanceof ErrorExpr // TODO } from ControlFlowNode n, string s diff --git a/java/ql/consistency-queries/children.ql b/java/ql/consistency-queries/children.ql index 9401c8785e4..b22fd56d044 100644 --- a/java/ql/consistency-queries/children.ql +++ b/java/ql/consistency-queries/children.ql @@ -41,7 +41,12 @@ predicate gapInChildren(Element e, int i) { // -1 can be skipped (type arguments from -2 down, no qualifier at -1, // then arguments from 0). // Can we also skip arguments, e.g. due to defaults for parameters? - not (e instanceof MethodAccess and e.getFile().isKotlinSourceFile()) + not (e instanceof MethodAccess and e.getFile().isKotlinSourceFile()) and + // Kotlin-extracted annotations can have missing children where a default + // value should be, because kotlinc doesn't load annotation defaults and we + // want to leave a space for another extractor to fill in the default if it + // is able. + not e instanceof Annotation } predicate lateFirstChild(Element e, int i) { @@ -59,7 +64,12 @@ predicate lateFirstChild(Element e, int i) { not (e instanceof LocalVariableDeclStmt and i = 1 and not exists(nthChildOf(e, 2))) and // For statements may or may not declare a new variable (child 0), or // have a condition (child 1). - not (e instanceof ForStmt and i = [1, 2]) + not (e instanceof ForStmt and i = [1, 2]) and + // Kotlin-extracted annotations can have missing children where a default + // value should be, because kotlinc doesn't load annotation defaults and we + // want to leave a space for another extractor to fill in the default if it + // is able. + not e instanceof Annotation } from Element e, int i, string problem diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.expected b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.expected new file mode 100644 index 00000000000..751777f3748 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.expected @@ -0,0 +1,301 @@ +User.java: +# 0| [CompilationUnit] User +# 1| 1: [Class] User +# 3| 2: [Method] user +# 3| 3: [TypeAccess] void +#-----| 4: (Parameters) +# 3| 0: [Parameter] a1 +# 3| 0: [TypeAccess] Ann1 +# 3| 1: [Parameter] a2 +# 3| 0: [TypeAccess] Ann2 +# 3| 5: [BlockStmt] { ... } +# 4| 0: [ExprStmt] ; +# 4| 0: [MethodAccess] x(...) +# 4| -1: [VarAccess] a1 +# 4| 1: [ExprStmt] ; +# 4| 0: [MethodAccess] z(...) +# 4| -1: [VarAccess] a2 +# 4| 2: [ExprStmt] ; +# 4| 0: [ClassInstanceExpr] new Annotated(...) +# 4| -3: [TypeAccess] Annotated +# 4| 3: [ExprStmt] ; +# 4| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByJava(...) +# 4| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByJava +# 4| 4: [ExprStmt] ; +# 4| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByJava(...) +# 4| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByJava +ktUser.kt: +# 0| [CompilationUnit] ktUser +# 1| 1: [Class] KtUser +# 1| 1: [Constructor] KtUser +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +# 3| 2: [Method] user +# 3| 3: [TypeAccess] Unit +# 3| 5: [BlockStmt] { ... } +# 4| 0: [LocalVariableDeclStmt] var ...; +# 4| 1: [LocalVariableDeclExpr] a +# 4| 0: [ClassInstanceExpr] new AnnotatedUsedByKotlin(...) +# 4| -3: [TypeAccess] AnnotatedUsedByKotlin +# 5| 1: [LocalVariableDeclStmt] var ...; +# 5| 1: [LocalVariableDeclExpr] b +# 5| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByKotlin(...) +# 5| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByKotlin +# 6| 2: [LocalVariableDeclStmt] var ...; +# 6| 1: [LocalVariableDeclExpr] c +# 6| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByKotlin(...) +# 6| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByKotlin +# 8| 3: [ExprStmt] ; +# 8| 0: [ImplicitCoercionToUnitExpr] +# 8| 0: [TypeAccess] Unit +# 8| 1: [MethodAccess] isJavaLetter(...) +# 8| -1: [TypeAccess] Character +# 8| 0: [CharacterLiteral] a +test.kt: +# 0| [CompilationUnit] test +# 4| 1: [Interface] Ann1 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 4| 1: [Method] x +# 4| 3: [TypeAccess] int +# 4| 2: [Method] y +# 4| 3: [TypeAccess] Ann2 +# 4| 3: [Method] z +# 4| 3: [TypeAccess] DayOfWeek +# 6| 2: [Interface] Ann2 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 6| 1: [Method] z +# 6| 3: [TypeAccess] String +# 6| 2: [Method] w +# 6| 3: [TypeAccess] Class +# 6| 0: [WildcardTypeAccess] ? ... +# 6| 3: [Method] v +# 6| 3: [TypeAccess] int[] +# 6| 4: [Method] u +# 6| 3: [TypeAccess] Ann3[] +# 6| 0: [TypeAccess] Ann3 +# 6| 5: [Method] t +# 6| 3: [TypeAccess] Class[] +# 6| 0: [TypeAccess] Class +# 6| 0: [WildcardTypeAccess] ? ... +# 8| 3: [Interface] Ann3 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 8| 1: [Method] a +# 8| 3: [TypeAccess] int +# 10| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +#-----| -2: (Generic Parameters) +# 10| 0: [TypeVariable] T +# 10| 1: [Method] x +# 10| 3: [TypeAccess] Class +# 10| 0: [TypeAccess] T +# 10| 2: [Method] y +# 10| 3: [TypeAccess] Class[] +# 10| 0: [TypeAccess] Class +# 10| 0: [TypeAccess] T +# 12| 6: [Interface] VarargAnnotation +#-----| -3: (Annotations) +# 0| 1: [Annotation] Repeatable +# 0| 1: [TypeLiteral] Container.class +# 0| 0: [TypeAccess] Container +# 0| 2: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 12| 3: [Annotation] Repeatable +# 0| 1: [Interface] Container +#-----| -3: (Annotations) +# 0| 1: [Annotation] RepeatableContainer +# 0| 2: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 0| 1: [Method] value +# 0| 3: [TypeAccess] VarargAnnotation[] +# 0| 0: [TypeAccess] VarargAnnotation +# 13| 2: [Method] x +# 13| 3: [TypeAccess] int[] +# 15| 7: [Interface] AnnWithDefaults +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 15| 1: [Method] x +# 15| 3: [TypeAccess] int +# 15| 2: [Method] y +# 15| 3: [TypeAccess] String +# 15| 3: [Method] z +# 15| 3: [TypeAccess] DayOfWeek +# 15| 4: [Method] w +# 15| 3: [TypeAccess] Ann3[] +# 15| 0: [TypeAccess] Ann3 +# 17| 8: [Class] Annotated +#-----| -3: (Annotations) +# 0| 1: [Annotation] Container +# 0| 1: [ArrayInit] {...} +# 19| 1: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 20| 2: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 21| 3: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 22| 4: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 23| 5: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 17| 2: [Annotation] Ann1 +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [Annotation] Ann2 +# 0| 1: [StringLiteral] "Hello" +# 0| 2: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 3: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 0| 4: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 2 +# 0| 5: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [TypeLiteral] int.class +# 0| 0: [TypeAccess] int +# 0| 3: [VarAccess] DayOfWeek.MONDAY +# 0| -1: [TypeAccess] DayOfWeek +# 18| 3: [Annotation] GenericAnnotation +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 24| 4: [Annotation] AnnWithDefaults +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [StringLiteral] "hello" +# 0| 3: [VarAccess] DayOfWeek.TUESDAY +# 0| -1: [TypeAccess] DayOfWeek +# 0| 4: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 25| 1: [Constructor] Annotated +# 17| 5: [BlockStmt] { ... } +# 17| 0: [SuperConstructorInvocationStmt] super(...) +# 25| 1: [BlockStmt] { ... } +# 27| 9: [Class] AnnotatedUsedByKotlin +#-----| -3: (Annotations) +# 0| 1: [Annotation] Container +# 0| 1: [ArrayInit] {...} +# 29| 1: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 30| 2: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 31| 3: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 32| 4: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 33| 5: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 27| 2: [Annotation] Ann1 +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [Annotation] Ann2 +# 0| 1: [StringLiteral] "Hello" +# 0| 2: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 3: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 0| 4: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 2 +# 0| 5: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [TypeLiteral] int.class +# 0| 0: [TypeAccess] int +# 0| 3: [VarAccess] DayOfWeek.MONDAY +# 0| -1: [TypeAccess] DayOfWeek +# 28| 3: [Annotation] GenericAnnotation +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 2: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 34| 4: [Annotation] AnnWithDefaults +# 0| 1: [IntegerLiteral] 1 +# 0| 2: [StringLiteral] "hello" +# 0| 3: [VarAccess] DayOfWeek.TUESDAY +# 0| -1: [TypeAccess] DayOfWeek +# 0| 4: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 35| 1: [Constructor] AnnotatedUsedByKotlin +# 27| 5: [BlockStmt] { ... } +# 27| 0: [SuperConstructorInvocationStmt] super(...) +# 35| 1: [BlockStmt] { ... } +# 37| 10: [Class] HasJavaDeprecatedAnnotationUsedByJava +#-----| -3: (Annotations) +# 37| 1: [Annotation] Deprecated +# 38| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByJava +# 37| 5: [BlockStmt] { ... } +# 37| 0: [SuperConstructorInvocationStmt] super(...) +# 38| 1: [BlockStmt] { ... } +# 40| 11: [Class] HasKotlinDeprecatedAnnotationUsedByJava +#-----| -3: (Annotations) +# 40| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "Kotlin deprecation message 1" +# 41| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByJava +# 40| 5: [BlockStmt] { ... } +# 40| 0: [SuperConstructorInvocationStmt] super(...) +# 41| 1: [BlockStmt] { ... } +# 43| 12: [Class] HasJavaDeprecatedAnnotationUsedByKotlin +#-----| -3: (Annotations) +# 43| 1: [Annotation] Deprecated +# 44| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByKotlin +# 43| 5: [BlockStmt] { ... } +# 43| 0: [SuperConstructorInvocationStmt] super(...) +# 44| 1: [BlockStmt] { ... } +# 46| 13: [Class] HasKotlinDeprecatedAnnotationUsedByKotlin +#-----| -3: (Annotations) +# 46| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "Kotlin deprecation message 2" +# 47| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByKotlin +# 46| 5: [BlockStmt] { ... } +# 46| 0: [SuperConstructorInvocationStmt] super(...) +# 47| 1: [BlockStmt] { ... } diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.qlref b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/User.java b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/User.java new file mode 100644 index 00000000000..004e770ba96 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/User.java @@ -0,0 +1,7 @@ +public class User { + + public static void user(Ann1 a1, Ann2 a2) { + a1.x(); a2.z(); new Annotated(); new HasJavaDeprecatedAnnotationUsedByJava(); new HasKotlinDeprecatedAnnotationUsedByJava(); + } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.expected b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.expected new file mode 100644 index 00000000000..76685549259 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.expected @@ -0,0 +1,5 @@ +| HasJavaDeprecatedAnnotationUsedByJava | java.lang.Deprecated | +| HasJavaDeprecatedAnnotationUsedByKotlin | java.lang.Deprecated | +| HasKotlinDeprecatedAnnotationUsedByJava | kotlin.Deprecated | +| HasKotlinDeprecatedAnnotationUsedByKotlin | kotlin.Deprecated | +| isJavaLetter | java.lang.Deprecated | diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.ql b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.ql new file mode 100644 index 00000000000..d8face48b56 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.ql @@ -0,0 +1,11 @@ +import java + +from Annotatable a, Annotation ann +where + ( + a.(Method).hasQualifiedName("java.lang", "Character", "isJavaLetter") or + a.(ClassOrInterface).fromSource() + ) and + ann = a.getAnAnnotation() and + ann.getType().getName() = "Deprecated" +select a.toString(), a.getAnAnnotation().getType().getQualifiedName() diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml new file mode 100644 index 00000000000..5fb4ebb6c1d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml @@ -0,0 +1,5 @@ +extensions: + - addsTo: + pack: integrationtest-annotation-id-consistency + extensible: extNegativeSummaryModel + data: [] diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt new file mode 100644 index 00000000000..cb593ce11f1 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt @@ -0,0 +1,11 @@ +public class KtUser { + + fun user() { + val a = AnnotatedUsedByKotlin() + val b = HasJavaDeprecatedAnnotationUsedByKotlin() + val c = HasKotlinDeprecatedAnnotationUsedByKotlin() + // Use a Java-defined function carrying a java.lang.Deprecated annotation: + java.lang.Character.isJavaLetter('a') + } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml new file mode 100644 index 00000000000..a0c9cdc98a3 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml @@ -0,0 +1,8 @@ +name: integrationtest-annotation-id-consistency +dependencies: + codeql/java-all: '*' + codeql/java-tests: '*' + codeql/java-queries: '*' +dataExtensions: + ext/*.model.yml + diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt new file mode 100644 index 00000000000..44746342ae6 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt @@ -0,0 +1,47 @@ +import kotlin.reflect.KClass +import java.time.DayOfWeek + +annotation class Ann1(val x: Int, val y: Ann2, val z: DayOfWeek) { } + +annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: Array, val t: Array>) { } + +annotation class Ann3(val a: Int) { } + +annotation class GenericAnnotation(val x: KClass, val y: Array>) { } + +@Repeatable +annotation class VarargAnnotation(vararg val x: Int) { } + +annotation class AnnWithDefaults(val x: Int = 1, val y: String = "hello", val z: DayOfWeek = DayOfWeek.TUESDAY, val w: Array = [Ann3(1)]) { } + +@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class)), DayOfWeek.MONDAY) +@GenericAnnotation(String::class, arrayOf(String::class, String::class)) +@VarargAnnotation +@VarargAnnotation(1) +@VarargAnnotation(1, 2) +@VarargAnnotation(*[1, 2, 3]) +@VarargAnnotation(*intArrayOf(1, 2, 3)) +@AnnWithDefaults +class Annotated { } + +@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class)), DayOfWeek.MONDAY) +@GenericAnnotation(String::class, arrayOf(String::class, String::class)) +@VarargAnnotation +@VarargAnnotation(1) +@VarargAnnotation(1, 2) +@VarargAnnotation(*[1, 2, 3]) +@VarargAnnotation(*intArrayOf(1, 2, 3)) +@AnnWithDefaults +class AnnotatedUsedByKotlin { } + +@java.lang.Deprecated +class HasJavaDeprecatedAnnotationUsedByJava + +@kotlin.Deprecated("Kotlin deprecation message 1") +class HasKotlinDeprecatedAnnotationUsedByJava + +@java.lang.Deprecated +class HasJavaDeprecatedAnnotationUsedByKotlin + +@kotlin.Deprecated("Kotlin deprecation message 2") +class HasKotlinDeprecatedAnnotationUsedByKotlin diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.py b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.py new file mode 100644 index 00000000000..49584531332 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * + +os.mkdir('out') +os.mkdir('out2') +run_codeql_database_create(["kotlinc test.kt -d out", "javac User.java -cp out -d out2", "kotlinc ktUser.kt -cp out -d out2"], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/PrintAst.expected b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/PrintAst.expected index 4f056c3c4fb..a81cadccd10 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/PrintAst.expected +++ b/java/ql/integration-tests/all-platforms/kotlin/gradle_kotlinx_serialization/PrintAst.expected @@ -1,7 +1,17 @@ app/src/main/kotlin/testProject/App.kt: # 0| [CompilationUnit] App # 7| 1: [Class] Project +#-----| -3: (Annotations) +# 7| 1: [Annotation] Serializable # 0| 1: [Constructor] Project +#-----| 1: (Annotations) +# 0| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly" +# 0| 2: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 3: [VarAccess] DeprecationLevel.HIDDEN +# 0| -1: [TypeAccess] DeprecationLevel #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -41,6 +51,8 @@ app/src/main/kotlin/testProject/App.kt: # 7| 0: [TypeAccess] Project # 7| 1: [VarAccess] language # 0| 2: [Method] component1 +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -53,9 +65,13 @@ app/src/main/kotlin/testProject/App.kt: # 0| 0: [VarAccess] this.language # 0| -1: [ThisAccess] this # 0| 4: [Method] copy +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] Project #-----| 4: (Parameters) # 8| 0: [Parameter] name +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 8| 0: [TypeAccess] String # 8| 1: [Parameter] language # 8| 0: [TypeAccess] int @@ -176,6 +192,8 @@ app/src/main/kotlin/testProject/App.kt: # 0| 2: [ReturnStmt] return ... # 0| 0: [VarAccess] result # 0| 8: [Method] toString +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -190,13 +208,21 @@ app/src/main/kotlin/testProject/App.kt: # 0| -1: [ThisAccess] this # 0| 6: [StringLiteral] ")" # 0| 9: [Method] write$Self +#-----| 1: (Annotations) +# 0| 1: [Annotation] JvmStatic # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] self +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Project # 0| 1: [Parameter] output +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] CompositeEncoder # 0| 2: [Parameter] serialDesc +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] SerialDescriptor # 7| 5: [BlockStmt] { ... } # 7| 0: [ExprStmt] ; @@ -214,9 +240,19 @@ app/src/main/kotlin/testProject/App.kt: # 7| 2: [MethodAccess] getLanguage(...) # 7| -1: [VarAccess] self # 7| 10: [Class] $serializer +#-----| -3: (Annotations) +# 0| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly" +# 0| 2: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 3: [VarAccess] DeprecationLevel.HIDDEN +# 0| -1: [TypeAccess] DeprecationLevel # 0| 1: [FieldDeclaration] SerialDescriptor descriptor; # 0| -1: [TypeAccess] SerialDescriptor # 0| 2: [Method] childSerializers +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] KSerializer[] # 0| 0: [TypeAccess] KSerializer # 0| 0: [WildcardTypeAccess] ? ... @@ -227,9 +263,13 @@ app/src/main/kotlin/testProject/App.kt: # 7| -1: [TypeAccess] KSerializer # 7| 0: [IntegerLiteral] 2 # 0| 3: [Method] deserialize +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] Project #-----| 4: (Parameters) # 0| 0: [Parameter] decoder +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Decoder # 7| 5: [BlockStmt] { ... } # 7| 0: [LocalVariableDeclStmt] var ...; @@ -365,6 +405,8 @@ app/src/main/kotlin/testProject/App.kt: # 7| 2: [VarAccess] tmp5_local1 # 7| 3: [NullLiteral] null # 0| 4: [Method] getDescriptor +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] SerialDescriptor # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -374,8 +416,12 @@ app/src/main/kotlin/testProject/App.kt: # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] encoder +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Encoder # 0| 1: [Parameter] value +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Project # 7| 5: [BlockStmt] { ... } # 7| 0: [LocalVariableDeclStmt] var ...; @@ -436,6 +482,8 @@ app/src/main/kotlin/testProject/App.kt: # 7| 0: [TypeAccess] GeneratedSerializer # 7| 11: [Class] Companion # 0| 1: [Method] serializer +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] KSerializer # 0| 0: [TypeAccess] Project # 7| 5: [BlockStmt] { ... } @@ -448,6 +496,8 @@ app/src/main/kotlin/testProject/App.kt: # 8| 12: [Constructor] Project #-----| 4: (Parameters) # 8| 0: [Parameter] name +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 8| 0: [TypeAccess] String # 8| 1: [Parameter] language # 8| 0: [TypeAccess] int @@ -464,6 +514,8 @@ app/src/main/kotlin/testProject/App.kt: # 8| -1: [TypeAccess] String # 8| 0: [VarAccess] name # 8| 14: [Method] getName +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 8| 3: [TypeAccess] String # 8| 5: [BlockStmt] { ... } # 8| 0: [ReturnStmt] return ... @@ -480,9 +532,21 @@ app/src/main/kotlin/testProject/App.kt: # 8| 0: [VarAccess] language # 10| 2: [Interface] Base # 11| 1: [Method] getId +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 11| 3: [TypeAccess] String # 14| 3: [Class] X +#-----| -3: (Annotations) +# 14| 1: [Annotation] Serializable # 0| 1: [Constructor] X +#-----| 1: (Annotations) +# 0| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly" +# 0| 2: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 3: [VarAccess] DeprecationLevel.HIDDEN +# 0| -1: [TypeAccess] DeprecationLevel #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -530,13 +594,21 @@ app/src/main/kotlin/testProject/App.kt: # 14| 0: [TypeAccess] X # 14| 1: [VarAccess] id # 0| 2: [Method] write$Self +#-----| 1: (Annotations) +# 0| 1: [Annotation] JvmStatic # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] self +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] X # 0| 1: [Parameter] output +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] CompositeEncoder # 0| 2: [Parameter] serialDesc +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] SerialDescriptor # 14| 5: [BlockStmt] { ... } # 14| 0: [ExprStmt] ; @@ -565,9 +637,19 @@ app/src/main/kotlin/testProject/App.kt: # 14| 2: [MethodAccess] getId(...) # 14| -1: [VarAccess] self # 14| 3: [Class] $serializer +#-----| -3: (Annotations) +# 0| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly" +# 0| 2: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 3: [VarAccess] DeprecationLevel.HIDDEN +# 0| -1: [TypeAccess] DeprecationLevel # 0| 1: [FieldDeclaration] SerialDescriptor descriptor; # 0| -1: [TypeAccess] SerialDescriptor # 0| 2: [Method] childSerializers +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] KSerializer[] # 0| 0: [TypeAccess] KSerializer # 0| 0: [WildcardTypeAccess] ? ... @@ -578,9 +660,13 @@ app/src/main/kotlin/testProject/App.kt: # 14| -1: [TypeAccess] KSerializer # 14| 0: [IntegerLiteral] 1 # 0| 3: [Method] deserialize +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] X #-----| 4: (Parameters) # 0| 0: [Parameter] decoder +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Decoder # 14| 5: [BlockStmt] { ... } # 14| 0: [LocalVariableDeclStmt] var ...; @@ -680,6 +766,8 @@ app/src/main/kotlin/testProject/App.kt: # 14| 1: [VarAccess] tmp4_local0 # 14| 2: [NullLiteral] null # 0| 4: [Method] getDescriptor +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] SerialDescriptor # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -689,8 +777,12 @@ app/src/main/kotlin/testProject/App.kt: # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] encoder +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] Encoder # 0| 1: [Parameter] value +#-----| -1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 0: [TypeAccess] X # 14| 5: [BlockStmt] { ... } # 14| 0: [LocalVariableDeclStmt] var ...; @@ -746,6 +838,8 @@ app/src/main/kotlin/testProject/App.kt: # 14| 0: [TypeAccess] GeneratedSerializer # 14| 4: [Class] Companion # 0| 1: [Method] serializer +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 0| 3: [TypeAccess] KSerializer # 0| 0: [TypeAccess] X # 14| 5: [BlockStmt] { ... } @@ -766,6 +860,8 @@ app/src/main/kotlin/testProject/App.kt: # 16| -1: [TypeAccess] String # 16| 0: [StringLiteral] "X" # 16| 7: [Method] getId +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 16| 3: [TypeAccess] String # 16| 5: [BlockStmt] { ... } # 16| 0: [ReturnStmt] return ... diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedInterface.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedInterface.java new file mode 100644 index 00000000000..db327383a95 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedInterface.java @@ -0,0 +1,10 @@ +import org.jetbrains.annotations.*; +import zpkg.A; + +public interface AnnotatedInterface { + + public @A @NotNull String notNullAnnotated(@A @NotNull String param); + + public @A @Nullable String nullableAnnotated(@A @Nullable String param); + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java new file mode 100644 index 00000000000..16671f5468f --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java @@ -0,0 +1,10 @@ +import org.jetbrains.annotations.*; +import zpkg.A; + +public class AnnotatedMethods implements AnnotatedInterface { + + public @A @NotNull String notNullAnnotated(@A @NotNull String param) { return param; } + + public @A @Nullable String nullableAnnotated(@A @Nullable String param) { return param; } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java new file mode 100644 index 00000000000..6031901c3a3 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java @@ -0,0 +1,8 @@ +public class JavaUser { + + public static void test(KotlinAnnotatedMethods km, KotlinDelegate kd) { + km.f(null); + kd.notNullAnnotated("Hello world"); + } + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt new file mode 100644 index 00000000000..06c1d580503 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt @@ -0,0 +1,9 @@ +import zpkg.A + +class KotlinAnnotatedMethods { + + @A fun f(@A m: AnnotatedMethods): String = m.notNullAnnotated("hello") + m.nullableAnnotated("world")!! + +} + +class KotlinDelegate(c: AnnotatedMethods) : AnnotatedInterface by c { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/NotNull.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/NotNull.java new file mode 100644 index 00000000000..60fc85ea9b8 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/NotNull.java @@ -0,0 +1,6 @@ +package org.jetbrains.annotations; + +public @interface NotNull { + String value() default ""; + Class exception() default Exception.class; +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/Nullable.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/Nullable.java new file mode 100644 index 00000000000..6cf82f2db31 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/Nullable.java @@ -0,0 +1,5 @@ +package org.jetbrains.annotations; + +public @interface Nullable { + String value() default ""; +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected new file mode 100644 index 00000000000..89eb06d26c3 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected @@ -0,0 +1,28 @@ +| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedInterface.java:6:46:6:47 | A | +| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedInterface.java:6:49:6:56 | NotNull | +| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedInterface.java:6:10:6:11 | A | +| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedInterface.java:6:13:6:20 | NotNull | +| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedInterface.java:8:48:8:49 | A | +| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedInterface.java:8:51:8:59 | Nullable | +| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedInterface.java:8:10:8:11 | A | +| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedInterface.java:8:13:8:21 | Nullable | +| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedMethods.java:6:46:6:47 | A | +| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedMethods.java:6:49:6:56 | NotNull | +| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedMethods.java:6:10:6:11 | A | +| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedMethods.java:6:13:6:20 | NotNull | +| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedMethods.java:8:48:8:49 | A | +| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedMethods.java:8:51:8:59 | Nullable | +| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedMethods.java:8:10:8:11 | A | +| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedMethods.java:8:13:8:21 | Nullable | +| ktUser.kt:0:0:0:0 | notNullAnnotated | parameter | ktUser.kt:0:0:0:0 | A | +| ktUser.kt:0:0:0:0 | notNullAnnotated | parameter | ktUser.kt:0:0:0:0 | NotNull | +| ktUser.kt:0:0:0:0 | notNullAnnotated | return value | ktUser.kt:0:0:0:0 | A | +| ktUser.kt:0:0:0:0 | notNullAnnotated | return value | ktUser.kt:0:0:0:0 | NotNull | +| ktUser.kt:0:0:0:0 | nullableAnnotated | parameter | ktUser.kt:0:0:0:0 | A | +| ktUser.kt:0:0:0:0 | nullableAnnotated | parameter | ktUser.kt:0:0:0:0 | Nullable | +| ktUser.kt:0:0:0:0 | nullableAnnotated | return value | ktUser.kt:0:0:0:0 | A | +| ktUser.kt:0:0:0:0 | nullableAnnotated | return value | ktUser.kt:0:0:0:0 | Nullable | +| ktUser.kt:5:6:5:105 | f | parameter | ktUser.kt:0:0:0:0 | NotNull | +| ktUser.kt:5:6:5:105 | f | parameter | ktUser.kt:5:12:5:13 | A | +| ktUser.kt:5:6:5:105 | f | return value | ktUser.kt:0:0:0:0 | NotNull | +| ktUser.kt:5:6:5:105 | f | return value | ktUser.kt:5:3:5:4 | A | diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py new file mode 100644 index 00000000000..6a27fa40a40 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py @@ -0,0 +1,7 @@ +from create_database_utils import * +import os + +os.mkdir('out') +os.mkdir('out2') +os.mkdir('out3') +run_codeql_database_create(["javac AnnotatedInterface.java AnnotatedMethods.java zpkg/A.java org/jetbrains/annotations/NotNull.java org/jetbrains/annotations/Nullable.java -d out", "kotlinc ktUser.kt -cp out -d out2", "javac JavaUser.java -cp out" + os.pathsep + "out2 -d out3"], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.ql b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.ql new file mode 100644 index 00000000000..def0233a5a0 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.ql @@ -0,0 +1,11 @@ +import java + +from Method m, string origin, Annotation a +where + m.fromSource() and + ( + origin = "return value" and a = m.getAnAnnotation() + or + origin = "parameter" and a = m.getAParameter().getAnAnnotation() + ) +select m, origin, a diff --git a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/zpkg/A.java b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/zpkg/A.java new file mode 100644 index 00000000000..93a36f72500 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/zpkg/A.java @@ -0,0 +1,3 @@ +package zpkg; + +public @interface A { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedContainer.java b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedContainer.java new file mode 100644 index 00000000000..13d1135669e --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedContainer.java @@ -0,0 +1,5 @@ +public @interface JavaDefinedContainer { + + public JavaDefinedRepeatable[] value(); + +} diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedRepeatable.java b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedRepeatable.java new file mode 100644 index 00000000000..5eaaf1e2ab2 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedRepeatable.java @@ -0,0 +1,3 @@ +@java.lang.annotation.Repeatable(JavaDefinedContainer.class) +public @interface JavaDefinedRepeatable { } + diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java new file mode 100644 index 00000000000..610c373cb0f --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java @@ -0,0 +1,9 @@ +@LocalRepeatable +@LocalRepeatable +@LibRepeatable +@LibRepeatable +@ExplicitContainerRepeatable +@ExplicitContainerRepeatable +@JavaDefinedRepeatable +@JavaDefinedRepeatable +public class JavaUser { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/lib.kt b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/lib.kt new file mode 100644 index 00000000000..3133d3d9e70 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/lib.kt @@ -0,0 +1,7 @@ +@Repeatable +public annotation class LibRepeatable { } + +annotation class KtDefinedContainer(val value: Array) { } + +@java.lang.annotation.Repeatable(KtDefinedContainer::class) +annotation class ExplicitContainerRepeatable() { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected new file mode 100644 index 00000000000..6ae3379e99f --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected @@ -0,0 +1,16 @@ +| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} | +| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} | +| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | JavaDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} | +| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | KtDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} | +| out/ExplicitContainerRepeatable.class:0:0:0:0 | ExplicitContainerRepeatable | out/ExplicitContainerRepeatable.class:0:0:0:0 | Repeatable | value | out/ExplicitContainerRepeatable.class:0:0:0:0 | KtDefinedContainer.class | +| out/ExplicitContainerRepeatable.class:0:0:0:0 | ExplicitContainerRepeatable | out/ExplicitContainerRepeatable.class:0:0:0:0 | Retention | value | out/ExplicitContainerRepeatable.class:0:0:0:0 | RUNTIME | +| out/JavaDefinedRepeatable.class:0:0:0:0 | JavaDefinedRepeatable | out/JavaDefinedRepeatable.class:0:0:0:0 | Repeatable | value | out/JavaDefinedRepeatable.class:0:0:0:0 | JavaDefinedContainer.class | +| out/KtDefinedContainer.class:0:0:0:0 | KtDefinedContainer | out/KtDefinedContainer.class:0:0:0:0 | Retention | value | out/KtDefinedContainer.class:0:0:0:0 | RUNTIME | +| out/LibRepeatable.class:0:0:0:0 | LibRepeatable | out/LibRepeatable.class:0:0:0:0 | Repeatable | value | out/LibRepeatable.class:0:0:0:0 | Container.class | +| out/LibRepeatable.class:0:0:0:0 | LibRepeatable | out/LibRepeatable.class:0:0:0:0 | Retention | value | out/LibRepeatable.class:0:0:0:0 | RUNTIME | +| test.kt:1:1:2:43 | LocalRepeatable | test.kt:0:0:0:0 | Repeatable | value | test.kt:0:0:0:0 | Container.class | +| test.kt:1:1:2:43 | LocalRepeatable | test.kt:0:0:0:0 | Retention | value | test.kt:0:0:0:0 | RetentionPolicy.RUNTIME | +| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | Container | value | test.kt:0:0:0:0 | {...} | +| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | Container | value | test.kt:0:0:0:0 | {...} | +| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | JavaDefinedContainer | value | test.kt:0:0:0:0 | {...} | +| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | KtDefinedContainer | value | test.kt:0:0:0:0 | {...} | diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.kt b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.kt new file mode 100644 index 00000000000..16a54a3e630 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.kt @@ -0,0 +1,12 @@ +@Repeatable +public annotation class LocalRepeatable { } + +@LocalRepeatable +@LocalRepeatable +@LibRepeatable +@LibRepeatable +@ExplicitContainerRepeatable +@ExplicitContainerRepeatable +@JavaDefinedRepeatable +@JavaDefinedRepeatable +public class User { } diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py new file mode 100644 index 00000000000..e0b7c69cb05 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py @@ -0,0 +1,7 @@ +from create_database_utils import * + +os.mkdir('out') +os.mkdir('out2') +runSuccessfully([get_cmd("kotlinc"), "lib.kt", "-d", "out"]) +runSuccessfully([get_cmd("javac"), "JavaDefinedContainer.java", "JavaDefinedRepeatable.java", "-d", "out"]) +run_codeql_database_create(["kotlinc test.kt -cp out -d out", "javac JavaUser.java -cp out -d out2"], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.ql b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.ql new file mode 100644 index 00000000000..701f6aed1ab --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.ql @@ -0,0 +1,11 @@ +import java + +from ClassOrInterface annotated, Annotation a, string valName, Expr val +where + a.getValue(valName) = val and + annotated = a.getAnnotatedElement() and + annotated.getName() in [ + "JavaDefinedRepeatable", "JavaDefinedContainer", "KtDefinedContainer", "LibRepeatable", + "ExplicitContainerRepeatable", "LocalRepeatable", "User", "JavaUser" + ] +select a.getAnnotatedElement(), a, valName, val diff --git a/java/ql/lib/change-notes/2022-12-09-default-extension-methods.md b/java/ql/lib/change-notes/2022-12-09-default-extension-methods.md new file mode 100644 index 00000000000..df9d23503da --- /dev/null +++ b/java/ql/lib/change-notes/2022-12-09-default-extension-methods.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The extraction of Kotlin extension methods has been improved when default parameter values are present. The dispatch and extension receiver parameters are extracted in the correct order. The `ExtensionMethod::getExtensionReceiverParameterIndex` predicate has been introduced to facilitate getting the correct extension parameter index. diff --git a/java/ql/lib/ext/dummy.model.yml b/java/ql/lib/ext/dummy.model.yml index 01642dccae6..e6139faabcf 100644 --- a/java/ql/lib/ext/dummy.model.yml +++ b/java/ql/lib/ext/dummy.model.yml @@ -14,5 +14,5 @@ extensions: data: [] - addsTo: pack: codeql/java-all - extensible: extNegativeSummaryModel + extensible: extNeutralModel data: [] \ No newline at end of file diff --git a/java/ql/lib/ext/generated/kotlinstdlib.model.yml b/java/ql/lib/ext/generated/kotlinstdlib.model.yml index a561d5dd572..4e8a73c048f 100644 --- a/java/ql/lib/ext/generated/kotlinstdlib.model.yml +++ b/java/ql/lib/ext/generated/kotlinstdlib.model.yml @@ -1861,7 +1861,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extNegativeSummaryModel + extensible: extNeutralModel data: - ["kotlin.annotation", "AnnotationRetention", "valueOf", "(String)", "generated"] - ["kotlin.annotation", "AnnotationRetention", "values", "()", "generated"] diff --git a/java/ql/lib/ext/generated/org.apache.commons.io.model.yml b/java/ql/lib/ext/generated/org.apache.commons.io.model.yml index f18303df59f..72ba13247bf 100644 --- a/java/ql/lib/ext/generated/org.apache.commons.io.model.yml +++ b/java/ql/lib/ext/generated/org.apache.commons.io.model.yml @@ -676,7 +676,7 @@ extensions: - addsTo: pack: codeql/java-all - extensible: extNegativeSummaryModel + extensible: extNeutralModel data: - ["org.apache.commons.io.charset", "CharsetDecoders", "CharsetDecoders", "()", "generated"] - ["org.apache.commons.io.charset", "CharsetEncoders", "CharsetEncoders", "()", "generated"] diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 28f994053a2..fa010ec88c0 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -37,7 +37,9 @@ class Annotation extends @annotation, Expr { } /** Gets the annotation type declaration for this annotation. */ - override AnnotationType getType() { result = Expr.super.getType() } + override AnnotationType getType() { + result = Expr.super.getType().(Interface).getSourceDeclaration() + } /** Gets the annotation element with the specified `name`. */ AnnotationElement getAnnotationElement(string name) { @@ -249,7 +251,7 @@ private predicate filteredAnnotValue(Annotation a, Method m, Expr val) { private predicate sourceAnnotValue(Annotation a, Method m, Expr val) { annotValue(a, m, val) and - val.getFile().getExtension() = "java" + val.getFile().isSourceFile() } /** An abstract representation of language elements that can be annotated. */ diff --git a/java/ql/lib/semmle/code/java/DependencyCounts.qll b/java/ql/lib/semmle/code/java/DependencyCounts.qll index 1010be48055..b34e774f1e1 100644 --- a/java/ql/lib/semmle/code/java/DependencyCounts.qll +++ b/java/ql/lib/semmle/code/java/DependencyCounts.qll @@ -91,7 +91,7 @@ predicate numDepends(RefType t, RefType dep, int value) { elem = a and usesType(a.getType(), dep) or elem = [a.getValue(_), a.getAnArrayValue(_)] and - elem.getFile().getExtension() = "java" and + elem.getFile().isSourceFile() and usesType(elem.(Expr).getType(), dep) ) or diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index fedcfc8ecbb..a10da9ecc9f 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1896,7 +1896,8 @@ class VarAccess extends Expr, @varaccess { class ExtensionReceiverAccess extends VarAccess { ExtensionReceiverAccess() { exists(Parameter p | - this.getVariable() = p and p.getPosition() = 0 and p.getCallable() instanceof ExtensionMethod + this.getVariable() = p and + p.isExtensionParameter() ) } diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 102006b3213..d55a0eefdec 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -327,18 +327,8 @@ class Callable extends StmtParent, Member, @callable { this instanceof Method and result instanceof Method and this.getName() + "$default" = result.getName() and - extraLeadingParams <= 1 and - ( - if ktExtensionFunctions(this, _, _) - then - // Both extension receivers are expected to occur at arg0, with any - // dispatch receiver inserted afterwards in the $default proxy's parameter list. - // Check the extension receiver matches here, and note regular args - // are bumped one position to the right. - regularParamsStartIdx = extraLeadingParams + 1 and - this.getParameterType(0).getErasure() = eraseRaw(result.getParameterType(0)) - else regularParamsStartIdx = extraLeadingParams - ) and + extraLeadingParams <= 1 and // 0 for static methods, 1 for instance methods + regularParamsStartIdx = extraLeadingParams and lastParamType instanceof TypeObject ) | @@ -824,4 +814,19 @@ class ExtensionMethod extends Method { KotlinType getExtendedKotlinType() { result = extendedKotlinType } override string getAPrimaryQlClass() { result = "ExtensionMethod" } + + /** + * Gets the index of the parameter that is the extension receiver. This is typically index 0. In case of `$default` + * extension methods that are defined as members, the index is 1. Index 0 is the dispatch receiver of the `$default` + * method. + */ + int getExtensionReceiverParameterIndex() { + if + exists(Method src | + this = src.getKotlinParameterDefaultsProxy() and + src.getNumberOfParameters() = this.getNumberOfParameters() - 3 // 2 extra parameters + 1 dispatch receiver + ) + then result = 1 + else result = 0 + } } diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index d6420f2e4ca..0e52be33149 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -120,7 +120,12 @@ private newtype TPrintAstNode = shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent } or TAnnotationsNode(Annotatable ann) { - shouldPrint(ann, _) and ann.hasDeclaredAnnotation() and not partOfAnnotation(ann) + shouldPrint(ann, _) and + ann.hasDeclaredAnnotation() and + not partOfAnnotation(ann) and + // The Kotlin compiler might add annotations that are only present in byte code, although the annotatable element is + // present in source code. + exists(Annotation a | a.getAnnotatedElement() = ann and shouldPrint(a, _)) } or TParametersNode(Callable c) { shouldPrint(c, _) and not c.hasNoParameters() } or TBaseTypesNode(ClassOrInterface ty) { shouldPrint(ty, _) } or @@ -293,19 +298,21 @@ final class AnnotationPartNode extends ExprStmtNode { override ElementNode getChild(int childIndex) { result.getElement() = - rank[childIndex](Element ch, string file, int line, int column | - ch = this.getAnAnnotationChild() and locationSortKeys(ch, file, line, column) + rank[childIndex](Element ch, string file, int line, int column, int idx | + ch = this.getAnnotationChild(idx) and locationSortKeys(ch, file, line, column) | - ch order by file, line, column + ch order by file, line, column, idx ) } - private Expr getAnAnnotationChild() { - result = element.(Annotation).getValue(_) + private Expr getAnnotationChild(int index) { + result = element.(Annotation).getValue(_) and + index >= 0 and + if exists(int x | x >= 0 | result.isNthChildOf(element, x)) + then result.isNthChildOf(element, index) + else result.isNthChildOf(element, -(index + 1)) or - result = element.(ArrayInit).getAnInit() - or - result = element.(ArrayInit).(Annotatable).getAnAnnotation() + result = element.(ArrayInit).getInit(index) } } @@ -672,10 +679,10 @@ final class AnnotationsNode extends PrintAstNode, TAnnotationsNode { override ElementNode getChild(int childIndex) { result.getElement() = - rank[childIndex](Element e, string file, int line, int column | - e = ann.getAnAnnotation() and locationSortKeys(e, file, line, column) + rank[childIndex](Element e, string file, int line, int column, string s | + e = ann.getAnAnnotation() and locationSortKeys(e, file, line, column) and s = e.toString() | - e order by file, line, column + e order by file, line, column, s ) } diff --git a/java/ql/lib/semmle/code/java/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll index 7be49acf546..82314824395 100644 --- a/java/ql/lib/semmle/code/java/Variable.qll +++ b/java/ql/lib/semmle/code/java/Variable.qll @@ -91,7 +91,7 @@ class Parameter extends Element, @param, LocalScopeVariable { /** Holds if this formal parameter is a parameter representing the dispatch receiver in an extension method. */ predicate isExtensionParameter() { - this.getPosition() = 0 and this.getCallable() instanceof ExtensionMethod + this.getPosition() = this.getCallable().(ExtensionMethod).getExtensionReceiverParameterIndex() } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 14773872ba0..10084c17c8d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -11,9 +11,9 @@ * `package; type; subtypes; name; signature; ext; input; kind; provenance` * - Summaries: * `package; type; subtypes; name; signature; ext; input; output; kind; provenance` - * - Negative Summaries: + * - Neutrals: * `package; type; name; signature; provenance` - * A negative summary is used to indicate that there is no flow via a callable. + * A neutral is used to indicate that there is no flow via a callable. * * The interpretation of a row is similar to API-graphs with a left-to-right * reading. @@ -122,30 +122,12 @@ private class SummaryModelCsvInternal extends Unit { abstract predicate row(string row); } -/** - * DEPRECATED: Define negative summary models as data extensions instead. - * - * A unit class for adding additional negative summary model rows. - * - * Extend this class to add additional negative summary definitions. - */ -deprecated class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal; - -private class NegativeSummaryModelCsvInternal extends Unit { - /** Holds if `row` specifies a negative summary definition. */ - abstract predicate row(string row); -} - private predicate sourceModelInternal(string row) { any(SourceModelCsvInternal s).row(row) } private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal s).row(row) } private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -private predicate negativeSummaryModelInternal(string row) { - any(NegativeSummaryModelCsvInternal s).row(row) -} - /** * Holds if an experimental source model exists for the given parameters. * This is only for experimental queries. @@ -313,25 +295,14 @@ predicate summaryModel( .summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) } -/** Holds if a summary model exists indicating there is no flow for the given parameters. */ -extensible predicate extNegativeSummaryModel( +/** Holds if a neutral model exists indicating there is no flow for the given parameters. */ +extensible predicate extNeutralModel( string package, string type, string name, string signature, string provenance ); -/** Holds if a summary model exists indicating there is no flow for the given parameters. */ -predicate negativeSummaryModel( - string package, string type, string name, string signature, string provenance -) { - exists(string row | - negativeSummaryModelInternal(row) and - row.splitAt(";", 0) = package and - row.splitAt(";", 1) = type and - row.splitAt(";", 2) = name and - row.splitAt(";", 3) = signature and - row.splitAt(";", 4) = provenance - ) - or - extNegativeSummaryModel(package, type, name, signature, provenance) +/** Holds if a neutral model exists indicating there is no flow for the given parameters. */ +predicate neutralModel(string package, string type, string name, string signature, string provenance) { + extNeutralModel(package, type, name, signature, provenance) } private predicate relevantPackage(string package) { @@ -472,8 +443,6 @@ module ModelValidation { sinkModelInternal(row) and expect = 9 and pred = "sink" or summaryModelInternal(row) and expect = 10 and pred = "summary" - or - negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and @@ -497,9 +466,9 @@ module ModelValidation { summaryModel(package, type, _, name, signature, ext, _, _, _, provenance) and pred = "summary" or - negativeSummaryModel(package, type, name, signature, provenance) and + neutralModel(package, type, name, signature, provenance) and ext = "" and - pred = "negative summary" + pred = "neutral" | not package.regexpMatch("[a-zA-Z0-9_\\.]*") and result = "Dubious package \"" + package + "\" in " + pred + " model." @@ -541,7 +510,7 @@ private predicate elementSpec( or summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _) or - negativeSummaryModel(package, type, name, signature, _) and ext = "" and subtypes = false + neutralModel(package, type, name, signature, _) and ext = "" and subtypes = false } private string paramsStringPart(Callable c, int i) { @@ -590,7 +559,7 @@ private Element interpretElement0( ) } -/** Gets the source/sink/summary/negativesummary element corresponding to the supplied parameters. */ +/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */ Element interpretElement( string package, string type, boolean subtypes, string name, string signature, string ext ) { diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll index c3366436d27..883b791835b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll @@ -120,8 +120,11 @@ private predicate correspondingKotlinParameterDefaultsArgSpec( exists(int oldArgParsed | oldArgParsed = AccessPathSyntax::AccessPath::parseInt(oldArgNumber.splitAt(",").trim()) | - if ktExtensionFunctions(originalCallable, _, _) and oldArgParsed = 0 - then defaultsArgSpec = "Argument[0]" + if + ktExtensionFunctions(originalCallable, _, _) and + ktExtensionFunctions(defaultsCallable, _, _) and + oldArgParsed = 0 + then defaultsArgSpec = "Argument[" + paramOffset + "]" // 1 if dispatch receiver is present, 0 otherwise. else defaultsArgSpec = "Argument[" + (oldArgParsed + paramOffset) + "]" + rest ) ) @@ -160,12 +163,12 @@ predicate summaryElement( } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the model is autogenerated. */ -predicate negativeSummaryElement(SummarizedCallableBase c, boolean generated) { +predicate neutralElement(SummarizedCallableBase c, boolean generated) { exists(string namespace, string type, string name, string signature, string provenance | - negativeSummaryModel(namespace, type, name, signature, provenance) and + neutralModel(namespace, type, name, signature, provenance) and generated = isGenerated(provenance) and c.asCallable() = interpretElement(namespace, type, false, name, signature, "") ) diff --git a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll index 061ec5dc68c..14445971b47 100644 --- a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll +++ b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll @@ -298,8 +298,9 @@ private class PathNormalizeSanitizer extends MethodAccess { * what `getQualifier` actually gets in Java and Kotlin. */ private Expr getVisualQualifier(MethodAccess ma) { - if getSourceMethod(ma.getMethod()) instanceof ExtensionMethod - then result = ma.getArgument(0) + if ma.getMethod() instanceof ExtensionMethod + then + result = ma.getArgument(ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex()) else result = ma.getQualifier() } @@ -310,8 +311,11 @@ private Expr getVisualQualifier(MethodAccess ma) { */ bindingset[argPos] private Argument getVisualArgument(MethodAccess ma, int argPos) { - if getSourceMethod(ma.getMethod()) instanceof ExtensionMethod - then result = ma.getArgument(argPos + 1) + if ma.getMethod() instanceof ExtensionMethod + then + result = + ma.getArgument(argPos + ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex() + + 1) else result = ma.getArgument(argPos) } diff --git a/java/ql/src/Telemetry/SupportedExternalApis.ql b/java/ql/src/Telemetry/SupportedExternalApis.ql index 13c6473b580..5e45f8ba7e9 100644 --- a/java/ql/src/Telemetry/SupportedExternalApis.ql +++ b/java/ql/src/Telemetry/SupportedExternalApis.ql @@ -14,7 +14,7 @@ private predicate relevant(ExternalApi api) { not api.isUninteresting() and ( api.isSupported() or - api = any(FlowSummaryImpl::Public::NegativeSummarizedCallable nsc).asCallable() + api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() ) } diff --git a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql index b1721972dd3..9ef469da5b0 100644 --- a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -13,7 +13,7 @@ import ExternalApi private predicate relevant(ExternalApi api) { not api.isUninteresting() and not api.isSupported() and - not api = any(FlowSummaryImpl::Public::NegativeSummarizedCallable nsc).asCallable() + not api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable() } from string apiName, int usages diff --git a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll index 0d13340b55d..b6bc910484b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -86,7 +86,7 @@ bindingset[unsafeExpression] predicate isMybatisCollectionTypeSqlInjection( DataFlow::Node node, MethodAccess ma, string unsafeExpression ) { - not unsafeExpression.regexpMatch("\\$\\{" + getAMybatisConfigurationVariableKey() + "\\}") and + not unsafeExpression.regexpMatch("\\$\\{\\s*" + getAMybatisConfigurationVariableKey() + "\\s*\\}") and // The parameter type of the MyBatis method parameter is Map or List or Array. // SQL injection vulnerability caused by improper use of this parameter. // e.g. @@ -120,7 +120,7 @@ bindingset[unsafeExpression] predicate isMybatisXmlOrAnnotationSqlInjection( DataFlow::Node node, MethodAccess ma, string unsafeExpression ) { - not unsafeExpression.regexpMatch("\\$\\{" + getAMybatisConfigurationVariableKey() + "\\}") and + not unsafeExpression.regexpMatch("\\$\\{\\s*" + getAMybatisConfigurationVariableKey() + "\\s*\\}") and ( // The method parameters use `@Param` annotation. Due to improper use of this parameter, SQL injection vulnerabilities are caused. // e.g. @@ -128,11 +128,15 @@ predicate isMybatisXmlOrAnnotationSqlInjection( // ```java // @Select(select id,name from test order by ${orderby,jdbcType=VARCHAR}) // void test(@Param("orderby") String name); + // + // @Select(select id,name from test where name = ${ user . name }) + // void test(@Param("user") User u); // ``` exists(Annotation annotation | unsafeExpression - .matches("${" + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + - "%}") and + .regexpMatch("\\$\\{\\s*" + + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + + "\\b[^}]*\\}") and annotation.getType() instanceof TypeParam and ma.getAnArgument() = node.asExpr() and annotation.getTarget() = @@ -140,6 +144,7 @@ predicate isMybatisXmlOrAnnotationSqlInjection( ) or // MyBatis default parameter sql injection vulnerabilities.the default parameter form of the method is arg[0...n] or param[1...n]. + // When compiled with '-parameters' compiler option, the parameter can be reflected in SQL statement as named in method signature. // e.g. // // ```java @@ -149,9 +154,12 @@ predicate isMybatisXmlOrAnnotationSqlInjection( exists(int i | not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and ( - unsafeExpression.matches("${param" + (i + 1) + "%}") + unsafeExpression.regexpMatch("\\$\\{\\s*param" + (i + 1) + "\\b[^}]*\\}") or - unsafeExpression.matches("${arg" + i + "%}") + unsafeExpression.regexpMatch("\\$\\{\\s*arg" + i + "\\b[^}]*\\}") + or + unsafeExpression + .regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*\\}") ) and ma.getArgument(i) = node.asExpr() ) @@ -166,7 +174,7 @@ predicate isMybatisXmlOrAnnotationSqlInjection( exists(int i, RefType t | not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and ma.getMethod().getParameterType(i).getName() = t.getName() and - unsafeExpression.matches("${" + t.getAField().getName() + "%}") and + unsafeExpression.regexpMatch("\\$\\{\\s*" + t.getAField().getName() + "\\b[^}]*\\}") and ma.getArgument(i) = node.asExpr() ) or diff --git a/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp new file mode 100644 index 00000000000..bf0c2d4ef2f --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp @@ -0,0 +1,48 @@ + + + + + +

The Thread.sleep method is used to pause the execution of current thread for +specified time. When the sleep time is user-controlled, especially in the web application context, +it can be abused to cause all of a server's threads to sleep, leading to denial of service.

+
+ + +

To guard against this attack, consider specifying an upper range of allowed sleep time or adopting +the producer/consumer design pattern with Object.wait method to avoid performance +problems or even resource exhaustion. For more information, refer to the concurrency tutorial of Oracle +listed below or java/ql/src/Likely Bugs/Concurrency queries of CodeQL.

+
+ + +

The following example shows a bad situation and a good situation respectively. In the bad situation, +a thread sleep time comes directly from user input. In the good situation, an upper +range check on the maximum sleep time allowed is enforced.

+ +
+ + +
  • +Snyk: +Denial of Service (DoS) +in com.googlecode.gwtupload:gwtupload. +
  • +
  • +gwtupload: +[Fix DOS issue] Updating the +AbstractUploadListener.java file. +
  • +
  • +The blog of a gypsy engineer: + +CVE-2019-17555: DoS via Retry-After header in Apache Olingo. +
  • +
  • +Oracle: +The Java Concurrency Tutorials +
  • +
    +
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql index 3c3c58da449..f66235994b0 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql @@ -3,7 +3,7 @@ * @description Using user input directly to control a thread's sleep time could lead to * performance problems or even resource exhaustion. * @kind path-problem - * @id java/thread-resource-abuse + * @id java/local-thread-resource-abuse * @problem.severity recommendation * @tags security * external/cwe/cwe-400 diff --git a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNeutralModels.ql similarity index 60% rename from java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql rename to java/ql/src/utils/model-generator/CaptureNeutralModels.ql index a6f6e5f26e5..96744de89b6 100644 --- a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureNeutralModels.ql @@ -1,8 +1,8 @@ /** - * @name Capture negative summary models. - * @description Finds negative summary models to be used by other queries. + * @name Capture neutral models. + * @description Finds neutral models to be used by other queries. * @kind diagnostic - * @id java/utils/model-generator/negative-summary-models + * @id java/utils/model-generator/neutral-models * @tags model-generator */ diff --git a/java/ql/src/utils/model-generator/RegenerateModels.py b/java/ql/src/utils/model-generator/RegenerateModels.py index f89873339f5..6bea57793a0 100755 --- a/java/ql/src/utils/model-generator/RegenerateModels.py +++ b/java/ql/src/utils/model-generator/RegenerateModels.py @@ -2,7 +2,6 @@ # Tool to regenerate existing framework CSV models. -from pathlib import Path import json import os import shutil @@ -37,7 +36,7 @@ def regenerateModel(lgtmSlug, extractedDb): modelFile = lgtmSlugToModelFile[lgtmSlug] codeQlRoot = findGitRoot() subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py", - "--with-summaries", "--with-sinks", "--with-negative-summaries", + "--with-summaries", "--with-sinks", "--with-neutrals", extractedDb, modelFile]) print("Regenerated " + modelFile) shutil.rmtree(tmpDir) diff --git a/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql b/java/ql/src/utils/modelconverter/ExtractNeutrals.ql similarity index 50% rename from java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql rename to java/ql/src/utils/modelconverter/ExtractNeutrals.ql index e762b3ee6e5..ad7cef84f04 100644 --- a/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql +++ b/java/ql/src/utils/modelconverter/ExtractNeutrals.ql @@ -1,7 +1,7 @@ /** - * @name Extract MaD negative summary model rows. - * @description This extracts the Models as data negative summary model rows. - * @id java/utils/modelconverter/generate-data-extensions-negative-summary + * @name Extract MaD neutral model rows. + * @description This extracts the Models as data neutral model rows. + * @id java/utils/modelconverter/generate-data-extensions-neutral */ import java @@ -9,6 +9,6 @@ import semmle.code.java.dataflow.ExternalFlow from string package, string type, string name, string signature, string provenance where - negativeSummaryModel(package, type, name, signature, provenance) and + neutralModel(package, type, name, signature, provenance) and provenance != "generated" select package, type, name, signature, provenance order by package, type, name, signature diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index f40b028ba6d..893c62191b3 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -58,9 +58,7 @@ private string asSummaryModel(TargetApiSpecific api, string input, string output + "generated" } -string asNegativeSummaryModel(TargetApiSpecific api) { - result = asPartialNegativeModel(api) + "generated" -} +string asNeutralModel(TargetApiSpecific api) { result = asPartialNeutralModel(api) + "generated" } /** * Gets the value summary model for `api` with `input` and `output`. diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 6e9fe7c29b2..af46170f5a3 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -131,9 +131,9 @@ string asPartialModel(TargetApiSpecific api) { } /** - * Computes the first 4 columns for negative CSV rows. + * Computes the first 4 columns for neutral CSV rows. */ -string asPartialNegativeModel(TargetApiSpecific api) { +string asPartialNeutralModel(TargetApiSpecific api) { exists(string type, string name, string parameters | partialModel(api, type, name, parameters) and result = diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll index 4b5293e63cd..04e87d9a385 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll @@ -77,10 +77,10 @@ string captureFlow(DataFlowTargetApi api) { } /** - * Gets the negative summary for `api`, if any. - * A negative summary is generated, if there does not exist any positive flow. + * Gets the neutral summary for `api`, if any. + * A neutral model is generated, if there does not exist any summary model. */ string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and - result = asNegativeSummaryModel(api) + result = asNeutralModel(api) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected index 1aedc93eb9a..dd3f886ccb1 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected @@ -1,30 +1,45 @@ edges | MybatisSqlInjection.java:62:19:62:43 | name : String | MybatisSqlInjection.java:63:35:63:38 | name : String | | MybatisSqlInjection.java:63:35:63:38 | name : String | MybatisSqlInjectionService.java:48:19:48:29 | name : String | -| MybatisSqlInjection.java:94:20:94:44 | name : String | MybatisSqlInjection.java:95:36:95:39 | name : String | -| MybatisSqlInjection.java:95:36:95:39 | name : String | MybatisSqlInjectionService.java:76:20:76:30 | name : String | -| MybatisSqlInjection.java:99:20:99:43 | age : String | MybatisSqlInjection.java:100:36:100:38 | age : String | -| MybatisSqlInjection.java:100:36:100:38 | age : String | MybatisSqlInjectionService.java:80:20:80:29 | age : String | +| MybatisSqlInjection.java:67:46:67:70 | name : String | MybatisSqlInjection.java:68:40:68:43 | name : String | +| MybatisSqlInjection.java:68:40:68:43 | name : String | MybatisSqlInjectionService.java:54:32:54:42 | name : String | +| MybatisSqlInjection.java:99:20:99:44 | name : String | MybatisSqlInjection.java:100:36:100:39 | name : String | +| MybatisSqlInjection.java:100:36:100:39 | name : String | MybatisSqlInjectionService.java:80:20:80:30 | name : String | +| MybatisSqlInjection.java:104:20:104:43 | age : String | MybatisSqlInjection.java:105:36:105:38 | age : String | +| MybatisSqlInjection.java:105:36:105:38 | age : String | MybatisSqlInjectionService.java:84:20:84:29 | age : String | +| MybatisSqlInjection.java:109:46:109:70 | name : String | MybatisSqlInjection.java:110:40:110:43 | name : String | +| MybatisSqlInjection.java:110:40:110:43 | name : String | MybatisSqlInjectionService.java:88:32:88:42 | name : String | | MybatisSqlInjectionService.java:48:19:48:29 | name : String | MybatisSqlInjectionService.java:50:23:50:26 | name : String | | MybatisSqlInjectionService.java:50:3:50:9 | hashMap [post update] [] : String | MybatisSqlInjectionService.java:51:27:51:33 | hashMap | | MybatisSqlInjectionService.java:50:23:50:26 | name : String | MybatisSqlInjectionService.java:50:3:50:9 | hashMap [post update] [] : String | -| MybatisSqlInjectionService.java:76:20:76:30 | name : String | MybatisSqlInjectionService.java:77:28:77:31 | name | -| MybatisSqlInjectionService.java:80:20:80:29 | age : String | MybatisSqlInjectionService.java:81:28:81:30 | age | +| MybatisSqlInjectionService.java:54:32:54:42 | name : String | MybatisSqlInjectionService.java:55:32:55:35 | name | +| MybatisSqlInjectionService.java:80:20:80:30 | name : String | MybatisSqlInjectionService.java:81:28:81:31 | name | +| MybatisSqlInjectionService.java:84:20:84:29 | age : String | MybatisSqlInjectionService.java:85:28:85:30 | age | +| MybatisSqlInjectionService.java:88:32:88:42 | name : String | MybatisSqlInjectionService.java:89:32:89:35 | name | nodes | MybatisSqlInjection.java:62:19:62:43 | name : String | semmle.label | name : String | | MybatisSqlInjection.java:63:35:63:38 | name : String | semmle.label | name : String | -| MybatisSqlInjection.java:94:20:94:44 | name : String | semmle.label | name : String | -| MybatisSqlInjection.java:95:36:95:39 | name : String | semmle.label | name : String | -| MybatisSqlInjection.java:99:20:99:43 | age : String | semmle.label | age : String | -| MybatisSqlInjection.java:100:36:100:38 | age : String | semmle.label | age : String | +| MybatisSqlInjection.java:67:46:67:70 | name : String | semmle.label | name : String | +| MybatisSqlInjection.java:68:40:68:43 | name : String | semmle.label | name : String | +| MybatisSqlInjection.java:99:20:99:44 | name : String | semmle.label | name : String | +| MybatisSqlInjection.java:100:36:100:39 | name : String | semmle.label | name : String | +| MybatisSqlInjection.java:104:20:104:43 | age : String | semmle.label | age : String | +| MybatisSqlInjection.java:105:36:105:38 | age : String | semmle.label | age : String | +| MybatisSqlInjection.java:109:46:109:70 | name : String | semmle.label | name : String | +| MybatisSqlInjection.java:110:40:110:43 | name : String | semmle.label | name : String | | MybatisSqlInjectionService.java:48:19:48:29 | name : String | semmle.label | name : String | | MybatisSqlInjectionService.java:50:3:50:9 | hashMap [post update] [] : String | semmle.label | hashMap [post update] [] : String | | MybatisSqlInjectionService.java:50:23:50:26 | name : String | semmle.label | name : String | | MybatisSqlInjectionService.java:51:27:51:33 | hashMap | semmle.label | hashMap | -| MybatisSqlInjectionService.java:76:20:76:30 | name : String | semmle.label | name : String | -| MybatisSqlInjectionService.java:77:28:77:31 | name | semmle.label | name | -| MybatisSqlInjectionService.java:80:20:80:29 | age : String | semmle.label | age : String | -| MybatisSqlInjectionService.java:81:28:81:30 | age | semmle.label | age | +| MybatisSqlInjectionService.java:54:32:54:42 | name : String | semmle.label | name : String | +| MybatisSqlInjectionService.java:55:32:55:35 | name | semmle.label | name | +| MybatisSqlInjectionService.java:80:20:80:30 | name : String | semmle.label | name : String | +| MybatisSqlInjectionService.java:81:28:81:31 | name | semmle.label | name | +| MybatisSqlInjectionService.java:84:20:84:29 | age : String | semmle.label | age : String | +| MybatisSqlInjectionService.java:85:28:85:30 | age | semmle.label | age | +| MybatisSqlInjectionService.java:88:32:88:42 | name : String | semmle.label | name : String | +| MybatisSqlInjectionService.java:89:32:89:35 | name | semmle.label | name | subpaths #select | MybatisSqlInjectionService.java:51:27:51:33 | hashMap | MybatisSqlInjection.java:62:19:62:43 | name : String | MybatisSqlInjectionService.java:51:27:51:33 | hashMap | MyBatis annotation SQL injection might include code from $@ to $@. | MybatisSqlInjection.java:62:19:62:43 | name | this user input | SqlInjectionMapper.java:33:2:33:54 | Select | this SQL operation | +| MybatisSqlInjectionService.java:55:32:55:35 | name | MybatisSqlInjection.java:67:46:67:70 | name : String | MybatisSqlInjectionService.java:55:32:55:35 | name | MyBatis annotation SQL injection might include code from $@ to $@. | MybatisSqlInjection.java:67:46:67:70 | name | this user input | SqlInjectionMapper.java:36:2:36:72 | Select | this SQL operation | diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjection.java b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjection.java index a751d2ebb1c..856c1d0b299 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjection.java +++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjection.java @@ -63,6 +63,11 @@ public class MybatisSqlInjection { mybatisSqlInjectionService.bad9(name); } + @GetMapping(value = "msi10") + public void bad10(@RequestParam Integer id, @RequestParam String name) { + mybatisSqlInjectionService.bad10(id, name); + } + @GetMapping(value = "good1") public List good1(Integer id) { List result = mybatisSqlInjectionService.good1(id); @@ -99,4 +104,9 @@ public class MybatisSqlInjection { public void good3(@RequestParam String age) { mybatisSqlInjectionService.good3(age); } + + @GetMapping(value = "good4") + public void good4(@RequestParam Integer id, @RequestParam String name) { + mybatisSqlInjectionService.good4(id, name); + } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjectionService.java b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjectionService.java index c8e1ce9c3cb..6e334ea35dd 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjectionService.java +++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MybatisSqlInjectionService.java @@ -51,6 +51,10 @@ public class MybatisSqlInjectionService { sqlInjectionMapper.bad9(hashMap); } + public void bad10(Integer id, String name) { + sqlInjectionMapper.bad10(id, name); + } + public List good1(Integer id) { List result = sqlInjectionMapper.good1(id); return result; @@ -80,4 +84,8 @@ public class MybatisSqlInjectionService { public void good3(String age){ sqlInjectionMapper.good3(age); } + + public void good4(Integer id, String name) { + sqlInjectionMapper.good4(id, name); + } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.java b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.java index a39b26a3aea..a8f56b40bc3 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.java +++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.java @@ -33,6 +33,9 @@ public interface SqlInjectionMapper { @Select({"select * from test", "where id = ${name}"}) public Test bad9(HashMap map); + @Select({"select * from test where id = #{id} and name = '${ name }'"}) + String bad10(Integer id, String name); + List good1(Integer id); //using providers @@ -66,4 +69,6 @@ public interface SqlInjectionMapper { @Select("select * from user_info where age = #{age}") String good3(@Param("age") String age); + @Select({"select * from test where id = #{id} and name = #{name}"}) + String good4(Integer id, String name); } diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.xml b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.xml index 3f3d1f9ba77..a0d8d7a7970 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.xml +++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.xml @@ -12,7 +12,7 @@ - and name = ${test.name,jdbcType=VARCHAR} + and name = ${ test . name , jdbcType = VARCHAR } and id = #{test.id} diff --git a/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/PrintAst.expected index 816b559db7f..3f91fe4f141 100644 --- a/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/PrintAst.expected @@ -1,82 +1,21 @@ test.kt: # 0| [CompilationUnit] test # 3| 1: [Interface] A -# 3| 1: [Constructor] A -#-----| 4: (Parameters) -# 3| 0: [Parameter] c1 -# 3| 0: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 1: [Parameter] c2 -# 3| 0: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 0: [TypeAccess] CharSequence -# 3| 2: [Parameter] c3 -# 3| 0: [TypeAccess] Class -# 3| 0: [TypeAccess] String -# 3| 3: [Parameter] c4 -# 3| 0: [TypeAccess] Class[] -# 3| 0: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 5: [BlockStmt] { ... } -# 3| 0: [SuperConstructorInvocationStmt] super(...) -# 3| 1: [BlockStmt] { ... } -# 3| 0: [ExprStmt] ; -# 3| 0: [KtInitializerAssignExpr] ...=... -# 3| 0: [VarAccess] c1 -# 3| 1: [ExprStmt] ; -# 3| 0: [KtInitializerAssignExpr] ...=... -# 3| 0: [VarAccess] c2 -# 3| 2: [ExprStmt] ; -# 3| 0: [KtInitializerAssignExpr] ...=... -# 3| 0: [VarAccess] c3 -# 3| 3: [ExprStmt] ; -# 3| 0: [KtInitializerAssignExpr] ...=... -# 3| 0: [VarAccess] c4 -# 3| 2: [FieldDeclaration] Class c1; -# 3| -1: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 0: [VarAccess] c1 -# 3| 3: [Method] c1 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 3| 1: [Method] c1 # 3| 3: [TypeAccess] Class # 3| 0: [WildcardTypeAccess] ? ... -# 3| 5: [BlockStmt] { ... } -# 3| 0: [ReturnStmt] return ... -# 3| 0: [VarAccess] this.c1 -# 3| -1: [ThisAccess] this -# 3| 4: [FieldDeclaration] Class c2; -# 3| -1: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 0: [TypeAccess] CharSequence -# 3| 0: [VarAccess] c2 -# 3| 5: [Method] c2 +# 3| 2: [Method] c2 # 3| 3: [TypeAccess] Class # 3| 0: [WildcardTypeAccess] ? ... # 3| 0: [TypeAccess] CharSequence -# 3| 5: [BlockStmt] { ... } -# 3| 0: [ReturnStmt] return ... -# 3| 0: [VarAccess] this.c2 -# 3| -1: [ThisAccess] this -# 3| 6: [FieldDeclaration] Class c3; -# 3| -1: [TypeAccess] Class -# 3| 0: [TypeAccess] String -# 3| 0: [VarAccess] c3 -# 3| 7: [Method] c3 +# 3| 3: [Method] c3 # 3| 3: [TypeAccess] Class # 3| 0: [TypeAccess] String -# 3| 5: [BlockStmt] { ... } -# 3| 0: [ReturnStmt] return ... -# 3| 0: [VarAccess] this.c3 -# 3| -1: [ThisAccess] this -# 3| 8: [FieldDeclaration] Class[] c4; -# 3| -1: [TypeAccess] Class[] -# 3| 0: [TypeAccess] Class -# 3| 0: [WildcardTypeAccess] ? ... -# 3| 0: [VarAccess] c4 -# 3| 9: [Method] c4 +# 3| 4: [Method] c4 # 3| 3: [TypeAccess] Class[] # 3| 0: [TypeAccess] Class # 3| 0: [WildcardTypeAccess] ? ... -# 3| 5: [BlockStmt] { ... } -# 3| 0: [ReturnStmt] return ... -# 3| 0: [VarAccess] this.c4 -# 3| -1: [ThisAccess] this diff --git a/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/test.expected b/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/test.expected index ce28362cbca..0391e2d9b86 100644 --- a/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/test.expected +++ b/java/ql/test/kotlin/library-tests/annotation-accessor-result-type/test.expected @@ -1,35 +1,9 @@ classExprs -| test.kt:3:20:3:36 | ...=... | Class | | test.kt:3:20:3:36 | Class | Class | -| test.kt:3:20:3:36 | Class | Class | -| test.kt:3:20:3:36 | Class | Class | -| test.kt:3:20:3:36 | c1 | Class | -| test.kt:3:20:3:36 | c1 | Class | -| test.kt:3:20:3:36 | this.c1 | Class | -| test.kt:3:39:3:70 | ...=... | Class | | test.kt:3:39:3:70 | Class | Class | -| test.kt:3:39:3:70 | Class | Class | -| test.kt:3:39:3:70 | Class | Class | -| test.kt:3:39:3:70 | c2 | Class | -| test.kt:3:39:3:70 | c2 | Class | -| test.kt:3:39:3:70 | this.c2 | Class | -| test.kt:3:73:3:94 | ...=... | Class | | test.kt:3:73:3:94 | Class | Class | -| test.kt:3:73:3:94 | Class | Class | -| test.kt:3:73:3:94 | Class | Class | -| test.kt:3:73:3:94 | c3 | Class | -| test.kt:3:73:3:94 | c3 | Class | -| test.kt:3:73:3:94 | this.c3 | Class | -| test.kt:3:97:3:120 | ...=... | Class[] | -| test.kt:3:97:3:120 | Class | Class | -| test.kt:3:97:3:120 | Class | Class | | test.kt:3:97:3:120 | Class | Class | | test.kt:3:97:3:120 | Class[] | Class[] | -| test.kt:3:97:3:120 | Class[] | Class[] | -| test.kt:3:97:3:120 | Class[] | Class[] | -| test.kt:3:97:3:120 | c4 | Class[] | -| test.kt:3:97:3:120 | c4 | Class[] | -| test.kt:3:97:3:120 | this.c4 | Class[] | #select | test.kt:3:20:3:36 | c1 | Class | | test.kt:3:39:3:70 | c2 | Class | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/Annot0j.java b/java/ql/test/kotlin/library-tests/annotation_classes/Annot0j.java new file mode 100644 index 00000000000..acadc19cc97 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/Annot0j.java @@ -0,0 +1,3 @@ +public @interface Annot0j { + int abc() default 0; +} \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/Annot1j.java b/java/ql/test/kotlin/library-tests/annotation_classes/Annot1j.java new file mode 100644 index 00000000000..b3b1f072eee --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/Annot1j.java @@ -0,0 +1,15 @@ +public @interface Annot1j { + int a() default 2; + + String b() default "ab"; + + Class c() default X.class; + + Y d() default Y.A; + + Y[] e() default { Y.A, Y.B }; + + Annot0j f() default @Annot0j( + abc = 1 + ); +} \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected new file mode 100644 index 00000000000..c457b0811dd --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -0,0 +1,280 @@ +Annot0j.java: +# 0| [CompilationUnit] Annot0j +# 1| 1: [Interface] Annot0j +# 2| 1: [Method] abc +# 2| 3: [TypeAccess] int +Annot1j.java: +# 0| [CompilationUnit] Annot1j +# 1| 1: [Interface] Annot1j +# 2| 1: [Method] a +# 2| 3: [TypeAccess] int +# 4| 2: [Method] b +# 4| 3: [TypeAccess] String +# 6| 3: [Method] c +# 6| 3: [TypeAccess] Class<> +# 8| 4: [Method] d +# 8| 3: [TypeAccess] Y +# 10| 5: [Method] e +# 10| 3: [ArrayTypeAccess] ...[] +# 10| 0: [TypeAccess] Y +# 12| 6: [Method] f +# 12| 3: [TypeAccess] Annot0j +def.kt: +# 0| [CompilationUnit] def +# 0| 1: [Class] DefKt +# 46| 2: [Method] fn +#-----| 1: (Annotations) +# 45| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +#-----| 2: (Generic Parameters) +# 46| 0: [TypeVariable] T +# 46| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 46| 0: [Parameter] a +#-----| -1: (Annotations) +# 46| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 46| 0: [TypeAccess] Annot0k +# 46| 5: [BlockStmt] { ... } +# 47| 0: [ExprStmt] ; +# 47| 0: [MethodAccess] println(...) +# 47| -1: [TypeAccess] ConsoleKt +# 47| 0: [MethodAccess] a(...) +# 47| -1: [VarAccess] a +# 50| 1: [LocalVariableDeclStmt] var ...; +# 50| 1: [LocalVariableDeclExpr] x +# 50| 0: [IntegerLiteral] 10 +# 53| 3: [FieldDeclaration] int p; +#-----| -2: (Annotations) +# 56| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 53| -1: [TypeAccess] int +# 57| 0: [IntegerLiteral] 5 +# 57| 4: [Method] getP +#-----| 1: (Annotations) +# 54| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 57| 3: [TypeAccess] int +# 57| 5: [BlockStmt] { ... } +# 57| 0: [ReturnStmt] return ... +# 57| 0: [VarAccess] DefKt.p +# 57| -1: [TypeAccess] DefKt +# 57| 5: [Method] setP +#-----| 1: (Annotations) +# 55| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 57| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 57| 0: [Parameter] +# 57| 0: [TypeAccess] int +# 57| 5: [BlockStmt] { ... } +# 57| 0: [ExprStmt] ; +# 57| 0: [AssignExpr] ...=... +# 57| 0: [VarAccess] DefKt.p +# 57| -1: [TypeAccess] DefKt +# 57| 1: [VarAccess] +# 59| 6: [ExtensionMethod] myExtension +# 59| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 59| 0: [Parameter] +#-----| -1: (Annotations) +# 59| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 59| 0: [TypeAccess] String +# 59| 5: [BlockStmt] { ... } +# 5| 2: [Interface] Annot0k +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 0| 2: [Annotation] Target +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] ElementType.TYPE +# 0| -1: [TypeAccess] ElementType +# 0| 2: [VarAccess] ElementType.FIELD +# 0| -1: [TypeAccess] ElementType +# 0| 3: [VarAccess] ElementType.METHOD +# 0| -1: [TypeAccess] ElementType +# 0| 4: [VarAccess] ElementType.PARAMETER +# 0| -1: [TypeAccess] ElementType +# 0| 5: [VarAccess] ElementType.CONSTRUCTOR +# 0| -1: [TypeAccess] ElementType +# 0| 6: [VarAccess] ElementType.LOCAL_VARIABLE +# 0| -1: [TypeAccess] ElementType +# 0| 7: [VarAccess] ElementType.ANNOTATION_TYPE +# 0| -1: [TypeAccess] ElementType +# 0| 8: [VarAccess] ElementType.TYPE_PARAMETER +# 0| -1: [TypeAccess] ElementType +# 0| 9: [VarAccess] ElementType.TYPE_USE +# 0| -1: [TypeAccess] ElementType +# 5| 3: [Annotation] Target +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] AnnotationTarget.CLASS +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 2: [VarAccess] AnnotationTarget.ANNOTATION_CLASS +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 3: [VarAccess] AnnotationTarget.TYPE_PARAMETER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 4: [VarAccess] AnnotationTarget.PROPERTY +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 5: [VarAccess] AnnotationTarget.FIELD +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 6: [VarAccess] AnnotationTarget.LOCAL_VARIABLE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 7: [VarAccess] AnnotationTarget.VALUE_PARAMETER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 8: [VarAccess] AnnotationTarget.CONSTRUCTOR +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 9: [VarAccess] AnnotationTarget.FUNCTION +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 10: [VarAccess] AnnotationTarget.PROPERTY_GETTER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 11: [VarAccess] AnnotationTarget.PROPERTY_SETTER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 12: [VarAccess] AnnotationTarget.TYPE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 13: [VarAccess] AnnotationTarget.FILE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 14: [VarAccess] AnnotationTarget.TYPEALIAS +# 0| -1: [TypeAccess] AnnotationTarget +# 21| 1: [Method] a +#-----| 1: (Annotations) +# 21| 1: [Annotation] JvmName +# 0| 1: [StringLiteral] "a" +# 21| 3: [TypeAccess] int +# 23| 3: [Interface] Annot1k +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 23| 2: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 25| 1: [Method] a +# 25| 3: [TypeAccess] int +# 26| 2: [Method] b +# 26| 3: [TypeAccess] String +# 27| 3: [Method] c +# 27| 3: [TypeAccess] Class +# 27| 0: [WildcardTypeAccess] ? ... +# 28| 4: [Method] d +# 28| 3: [TypeAccess] Y +# 29| 5: [Method] e +# 29| 3: [TypeAccess] Y[] +# 29| 0: [TypeAccess] Y +# 30| 6: [Method] f +# 30| 3: [TypeAccess] Annot0k +# 33| 4: [Class] X +# 33| 1: [Constructor] X +# 33| 5: [BlockStmt] { ... } +# 33| 0: [SuperConstructorInvocationStmt] super(...) +# 33| 1: [BlockStmt] { ... } +# 34| 5: [Class] Y +# 0| 2: [Method] valueOf +# 0| 3: [TypeAccess] Y +#-----| 4: (Parameters) +# 0| 0: [Parameter] value +# 0| 0: [TypeAccess] String +# 0| 3: [Method] values +# 0| 3: [TypeAccess] Y[] +# 0| 0: [TypeAccess] Y +# 34| 4: [Constructor] Y +# 34| 5: [BlockStmt] { ... } +# 34| 0: [ExprStmt] ; +# 34| 0: [ClassInstanceExpr] new Enum(...) +# 34| -3: [TypeAccess] Enum +# 34| 0: [TypeAccess] Y +# 34| 0: [NullLiteral] null +# 34| 1: [IntegerLiteral] 0 +# 34| 1: [BlockStmt] { ... } +# 35| 5: [FieldDeclaration] Y A; +# 35| -1: [TypeAccess] Y +# 35| 0: [ClassInstanceExpr] new Y(...) +# 35| -3: [TypeAccess] Y +# 35| 6: [FieldDeclaration] Y B; +# 35| -1: [TypeAccess] Y +# 35| 0: [ClassInstanceExpr] new Y(...) +# 35| -3: [TypeAccess] Y +# 35| 7: [FieldDeclaration] Y C; +# 35| -1: [TypeAccess] Y +# 35| 0: [ClassInstanceExpr] new Y(...) +# 35| -3: [TypeAccess] Y +# 38| 6: [Class] Z +#-----| -3: (Annotations) +# 38| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 39| 2: [Annotation] Annot1k +# 0| 1: [IntegerLiteral] 2 +# 0| 2: [StringLiteral] "ab" +# 0| 3: [TypeLiteral] X.class +# 0| 0: [TypeAccess] X +# 0| 4: [VarAccess] Y.B +# 0| -1: [TypeAccess] Y +# 0| 5: [ArrayInit] {...} +# 0| 1: [VarAccess] Y.C +# 0| -1: [TypeAccess] Y +# 0| 2: [VarAccess] Y.A +# 0| -1: [TypeAccess] Y +# 0| 6: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 42| 1: [Constructor] Z +#-----| 1: (Annotations) +# 41| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 41| 5: [BlockStmt] { ... } +# 42| 0: [SuperConstructorInvocationStmt] super(...) +# 42| 1: [BlockStmt] { ... } +use.java: +# 0| [CompilationUnit] use +# 1| 1: [Class] use +#-----| -1: (Base Types) +# 1| 0: [TypeAccess] Annot0k +# 3| 2: [Method] a +#-----| 1: (Annotations) +# 2| 1: [Annotation] Override +# 3| 3: [TypeAccess] int +# 3| 5: [BlockStmt] { ... } +# 3| 0: [ReturnStmt] return ... +# 3| 0: [IntegerLiteral] 1 +# 6| 3: [Method] annotationType +#-----| 1: (Annotations) +# 5| 1: [Annotation] Override +# 6| 3: [TypeAccess] Class +# 6| 0: [WildcardTypeAccess] ? ... +# 6| 0: [TypeAccess] Annotation +# 6| 5: [BlockStmt] { ... } +# 7| 0: [ReturnStmt] return ... +# 7| 0: [NullLiteral] null +# 14| 4: [Class] Z +#-----| -3: (Annotations) +# 10| 1: [Annotation] Annot0j +# 10| 1: [IntegerLiteral] 1 +# 11| 2: [Annotation] Annot1j +# 11| 1: [IntegerLiteral] 1 +# 11| 2: [StringLiteral] "ac" +# 11| 3: [TypeLiteral] X.class +# 11| 0: [TypeAccess] X +# 11| 4: [VarAccess] Y.B +# 11| -1: [TypeAccess] Y +# 11| 5: [ArrayInit] {...} +# 11| 3: [VarAccess] Y.C +# 11| -1: [TypeAccess] Y +# 11| 4: [VarAccess] Y.A +# 11| -1: [TypeAccess] Y +# 11| 6: [Annotation] Annot0j +# 11| 1: [IntegerLiteral] 2 +# 12| 3: [Annotation] Annot0k +# 12| 1: [IntegerLiteral] 1 +# 13| 4: [Annotation] Annot1k +# 13| 1: [IntegerLiteral] 1 +# 13| 2: [StringLiteral] "ac" +# 13| 3: [TypeLiteral] X.class +# 13| 0: [TypeAccess] X +# 13| 4: [VarAccess] Y.B +# 13| -1: [TypeAccess] Y +# 13| 5: [ArrayInit] {...} +# 13| 3: [VarAccess] Y.C +# 13| -1: [TypeAccess] Y +# 13| 4: [VarAccess] Y.A +# 13| -1: [TypeAccess] Y +# 13| 6: [Annotation] Annot0k +# 13| 1: [IntegerLiteral] 2 diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.qlref b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected index 240c4bb055b..b04dd33d2e7 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -1,2 +1,82 @@ -| def.kt:2:1:2:31 | SomeAnnotation | Interface | -| use.java:2:23:2:25 | use | Class | +annotationDeclarations +| Annot0j.java:1:19:1:25 | Annot0j | Annot0j.java:2:9:2:11 | abc | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:2:9:2:9 | a | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:4:12:4:12 | b | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:6:11:6:11 | c | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:8:7:8:7 | d | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:10:9:10:9 | e | +| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:12:13:12:13 | f | +| def.kt:5:1:21:60 | Annot0k | def.kt:21:44:21:59 | a | +| def.kt:23:1:31:1 | Annot1k | def.kt:25:5:25:18 | a | +| def.kt:23:1:31:1 | Annot1k | def.kt:26:5:26:24 | b | +| def.kt:23:1:31:1 | Annot1k | def.kt:27:5:27:31 | c | +| def.kt:23:1:31:1 | Annot1k | def.kt:28:5:28:18 | d | +| def.kt:23:1:31:1 | Annot1k | def.kt:29:5:29:32 | e | +| def.kt:23:1:31:1 | Annot1k | def.kt:30:5:30:31 | f | +annotations +| def.kt:0:0:0:0 | Annot0k | def.kt:39:1:39:40 | Annot1k | def.kt:5:1:21:60 | Annot0k | +| def.kt:23:1:23:8 | Annot0k | def.kt:23:1:31:1 | Annot1k | def.kt:5:1:21:60 | Annot0k | +| def.kt:38:1:38:17 | Annot0k | def.kt:38:1:43:1 | Z | def.kt:5:1:21:60 | Annot0k | +| def.kt:39:1:39:40 | Annot1k | def.kt:38:1:43:1 | Z | def.kt:23:1:31:1 | Annot1k | +| def.kt:41:5:41:12 | Annot0k | def.kt:42:5:42:19 | Z | def.kt:5:1:21:60 | Annot0k | +| def.kt:45:1:45:8 | Annot0k | def.kt:46:1:51:1 | fn | def.kt:5:1:21:60 | Annot0k | +| def.kt:46:21:46:28 | Annot0k | def.kt:46:21:46:39 | a | def.kt:5:1:21:60 | Annot0k | +| def.kt:54:1:54:12 | Annot0k | def.kt:57:1:57:23 | getP | def.kt:5:1:21:60 | Annot0k | +| def.kt:55:1:55:12 | Annot0k | def.kt:57:1:57:23 | setP | def.kt:5:1:21:60 | Annot0k | +| def.kt:56:1:56:14 | Annot0k | def.kt:53:1:57:23 | p | def.kt:5:1:21:60 | Annot0k | +| def.kt:59:5:59:21 | Annot0k | def.kt:59:5:59:28 | | def.kt:5:1:21:60 | Annot0k | +| use.java:10:5:10:21 | Annot0j | use.java:14:18:14:18 | Z | Annot0j.java:1:19:1:25 | Annot0j | +| use.java:11:5:11:90 | Annot1j | use.java:14:18:14:18 | Z | Annot1j.java:1:19:1:25 | Annot1j | +| use.java:11:73:11:89 | Annot0j | use.java:11:5:11:90 | Annot1j | Annot0j.java:1:19:1:25 | Annot0j | +| use.java:12:5:12:19 | Annot0k | use.java:14:18:14:18 | Z | def.kt:5:1:21:60 | Annot0k | +| use.java:13:5:13:88 | Annot1k | use.java:14:18:14:18 | Z | def.kt:23:1:31:1 | Annot1k | +| use.java:13:73:13:87 | Annot0k | use.java:13:5:13:88 | Annot1k | def.kt:5:1:21:60 | Annot0k | +annotationValues +| def.kt:0:0:0:0 | Annot0k | def.kt:0:0:0:0 | 1 | +| def.kt:0:0:0:0 | Retention | def.kt:0:0:0:0 | RetentionPolicy.RUNTIME | +| def.kt:0:0:0:0 | Retention | def.kt:0:0:0:0 | RetentionPolicy.RUNTIME | +| def.kt:0:0:0:0 | Target | def.kt:0:0:0:0 | {...} | +| def.kt:5:1:20:1 | Target | def.kt:0:0:0:0 | {...} | +| def.kt:21:26:21:42 | JvmName | def.kt:0:0:0:0 | "a" | +| def.kt:23:1:23:8 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:38:1:38:17 | Annot0k | def.kt:0:0:0:0 | 1 | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | 2 | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | "ab" | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | Annot0k | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | X.class | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | Y.B | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | {...} | +| def.kt:41:5:41:12 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:45:1:45:8 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:46:21:46:28 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:54:1:54:12 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:55:1:55:12 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:56:1:56:14 | Annot0k | def.kt:0:0:0:0 | 0 | +| def.kt:59:5:59:21 | Annot0k | def.kt:0:0:0:0 | 0 | +| use.java:10:5:10:21 | Annot0j | use.java:10:20:10:20 | 1 | +| use.java:11:5:11:90 | Annot1j | use.java:11:18:11:18 | 1 | +| use.java:11:5:11:90 | Annot1j | use.java:11:25:11:28 | "ac" | +| use.java:11:5:11:90 | Annot1j | use.java:11:35:11:41 | X.class | +| use.java:11:5:11:90 | Annot1j | use.java:11:48:11:50 | Y.B | +| use.java:11:5:11:90 | Annot1j | use.java:11:57:11:66 | {...} | +| use.java:11:5:11:90 | Annot1j | use.java:11:73:11:89 | Annot0j | +| use.java:11:73:11:89 | Annot0j | use.java:11:88:11:88 | 2 | +| use.java:12:5:12:19 | Annot0k | use.java:12:18:12:18 | 1 | +| use.java:13:5:13:88 | Annot1k | use.java:13:18:13:18 | 1 | +| use.java:13:5:13:88 | Annot1k | use.java:13:25:13:28 | "ac" | +| use.java:13:5:13:88 | Annot1k | use.java:13:35:13:41 | X.class | +| use.java:13:5:13:88 | Annot1k | use.java:13:48:13:50 | Y.B | +| use.java:13:5:13:88 | Annot1k | use.java:13:57:13:66 | {...} | +| use.java:13:5:13:88 | Annot1k | use.java:13:73:13:87 | Annot0k | +| use.java:13:73:13:87 | Annot0k | use.java:13:86:13:86 | 2 | +#select +| Annot0j.java:1:19:1:25 | Annot0j | Interface | +| Annot1j.java:1:19:1:25 | Annot1j | Interface | +| def.kt:0:0:0:0 | DefKt | Class | +| def.kt:5:1:21:60 | Annot0k | Interface | +| def.kt:23:1:31:1 | Annot1k | Interface | +| def.kt:33:1:33:10 | X | Class | +| def.kt:34:1:36:1 | Y | Class | +| def.kt:38:1:43:1 | Z | Class | +| use.java:1:14:1:16 | use | Class | +| use.java:14:18:14:18 | Z | Class | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql b/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql index 652ab21520f..936165cf023 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql @@ -3,3 +3,18 @@ import java from ClassOrInterface x where x.fromSource() select x, x.getPrimaryQlClasses() + +query predicate annotationDeclarations(AnnotationType at, AnnotationElement ae) { + at.fromSource() and + at.getAnAnnotationElement() = ae +} + +query predicate annotations(Annotation a, Element e, AnnotationType at) { + at.fromSource() and + a.getAnnotatedElement() = e and + at = a.getType() +} + +query predicate annotationValues(Annotation a, Expr v) { + a.getValue(_) = v and v.getFile().isSourceFile() +} diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt index 556973c4728..f499d1026fc 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt +++ b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt @@ -1,3 +1,62 @@ +@file:Annot0k -annotation class SomeAnnotation +import kotlin.reflect.KClass +@Target(AnnotationTarget.CLASS, + AnnotationTarget.ANNOTATION_CLASS, + AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.PROPERTY, + AnnotationTarget.FIELD, + AnnotationTarget.LOCAL_VARIABLE, // TODO + AnnotationTarget.VALUE_PARAMETER, + AnnotationTarget.CONSTRUCTOR, + AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER, + AnnotationTarget.TYPE, // TODO + //AnnotationTarget.EXPRESSION, // TODO + AnnotationTarget.FILE, // TODO + AnnotationTarget.TYPEALIAS // TODO +) +annotation class Annot0k(@get:JvmName("a") val abc: Int = 0) + +@Annot0k +annotation class Annot1k( + val a: Int = 2, + val b: String = "ab", + val c: KClass<*> = X::class, + val d: Y = Y.A, + val e: Array = [Y.A, Y.B], + val f: Annot0k = Annot0k(1) +) + +class X {} +enum class Y { + A,B,C +} + +@Annot0k(abc = 1) +@Annot1k(d = Y.B, e = arrayOf(Y.C, Y.A)) +class Z { + @Annot0k + constructor(){} +} + +@Annot0k +fun <@Annot0k T> fn(@Annot0k a: Annot0k) { + println(a.abc) + + @Annot0k + var x = 10 +} + +@Annot0k +@get:Annot0k +@set:Annot0k +@field:Annot0k +var p: @Annot0k Int = 5 + +fun @receiver:Annot0k String.myExtension() { } + +@Annot0k +typealias AAA = Z diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/use.java b/java/ql/test/kotlin/library-tests/annotation_classes/use.java index b848298e1ff..ec0dd0fa447 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/use.java +++ b/java/ql/test/kotlin/library-tests/annotation_classes/use.java @@ -1,3 +1,15 @@ +public class use implements Annot0k { + @Override + public int a() { return 1; } -public abstract class use implements SomeAnnotation {} + @Override + public Class annotationType() { + return null; + } + @Annot0j(abc = 1) + @Annot1j(a = 1, b = "ac", c = X.class, d = Y.B, e = {Y.C, Y.A}, f = @Annot0j(abc = 2)) + @Annot0k(a = 1) + @Annot1k(a = 1, b = "ac", c = X.class, d = Y.B, e = {Y.C, Y.A}, f = @Annot0k(a = 2)) + public class Z { } +} diff --git a/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected b/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected index 5a81043964b..cbcabc82bd5 100644 --- a/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected @@ -1,84 +1,12 @@ test.kt: # 0| [CompilationUnit] test # 1| 1: [Interface] Ann -# 1| 1: [Constructor] Ann -#-----| 4: (Parameters) -# 1| 0: [Parameter] arr1 -# 1| 0: [TypeAccess] String[] -# 1| 0: [TypeAccess] String -# 1| 1: [Parameter] arr2 -# 1| 0: [TypeAccess] int[] -# 1| 5: [BlockStmt] { ... } -# 1| 0: [SuperConstructorInvocationStmt] super(...) -# 1| 1: [BlockStmt] { ... } -# 1| 0: [ExprStmt] ; -# 1| 0: [KtInitializerAssignExpr] ...=... -# 1| 0: [VarAccess] arr1 -# 1| 1: [ExprStmt] ; -# 1| 0: [KtInitializerAssignExpr] ...=... -# 1| 0: [VarAccess] arr2 -# 1| 2: [Constructor] Ann -#-----| 4: (Parameters) -# 1| 0: [Parameter] p0 -# 1| 0: [TypeAccess] String[] -# 1| 1: [Parameter] p1 -# 1| 0: [TypeAccess] int[] -# 1| 2: [Parameter] p2 -# 1| 0: [TypeAccess] int -# 1| 3: [Parameter] p3 -# 1| 0: [TypeAccess] DefaultConstructorMarker -# 1| 5: [BlockStmt] { ... } -# 1| 0: [IfStmt] if (...) -# 1| 0: [EQExpr] ... == ... -# 1| 0: [AndBitwiseExpr] ... & ... -# 1| 0: [IntegerLiteral] 1 -# 1| 1: [VarAccess] p2 -# 1| 1: [IntegerLiteral] 0 -# 1| 1: [ExprStmt] ; -# 1| 0: [AssignExpr] ...=... -# 1| 0: [VarAccess] p0 -# 0| 1: [ArrayCreationExpr] new String[] -# 0| -2: [ArrayInit] {...} -# 0| 0: [StringLiteral] "hello" -# 0| 1: [StringLiteral] "world" -# 0| -1: [TypeAccess] String -# 0| 0: [IntegerLiteral] 2 -# 1| 1: [IfStmt] if (...) -# 1| 0: [EQExpr] ... == ... -# 1| 0: [AndBitwiseExpr] ... & ... -# 1| 0: [IntegerLiteral] 2 -# 1| 1: [VarAccess] p2 -# 1| 1: [IntegerLiteral] 0 -# 1| 1: [ExprStmt] ; -# 1| 0: [AssignExpr] ...=... -# 1| 0: [VarAccess] p1 -# 0| 1: [ArrayCreationExpr] new int[] -# 0| -2: [ArrayInit] {...} -# 0| 0: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 2: [IntegerLiteral] 3 -# 0| -1: [TypeAccess] int -# 0| 0: [IntegerLiteral] 3 -# 1| 2: [ThisConstructorInvocationStmt] this(...) -# 1| 0: [VarAccess] p0 -# 1| 1: [VarAccess] p1 -# 1| 3: [FieldDeclaration] String[] arr1; -# 1| -1: [TypeAccess] String[] -# 1| 0: [TypeAccess] String -# 1| 0: [VarAccess] arr1 -# 1| 4: [Method] arr1 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 1| 1: [Method] arr1 # 1| 3: [TypeAccess] String[] # 1| 0: [TypeAccess] String -# 1| 5: [BlockStmt] { ... } -# 1| 0: [ReturnStmt] return ... -# 1| 0: [VarAccess] this.arr1 -# 1| -1: [ThisAccess] this -# 1| 5: [Method] arr2 +# 1| 2: [Method] arr2 # 1| 3: [TypeAccess] int[] -# 1| 5: [BlockStmt] { ... } -# 1| 0: [ReturnStmt] return ... -# 1| 0: [VarAccess] this.arr2 -# 1| -1: [ThisAccess] this -# 1| 6: [FieldDeclaration] int[] arr2; -# 1| -1: [TypeAccess] int[] -# 1| 0: [VarAccess] arr2 diff --git a/java/ql/test/kotlin/library-tests/exprs/CONSISTENCY/cfgDeadEnds.expected b/java/ql/test/kotlin/library-tests/exprs/CONSISTENCY/cfgDeadEnds.expected index d7025aaef88..19cabccd05b 100644 --- a/java/ql/test/kotlin/library-tests/exprs/CONSISTENCY/cfgDeadEnds.expected +++ b/java/ql/test/kotlin/library-tests/exprs/CONSISTENCY/cfgDeadEnds.expected @@ -1,2 +1 @@ -| exprs.kt:278:52:278:66 | | ErrorExpr | unexpected dead end | | exprs.kt:278:52:278:66 | { ... } | BlockStmt | unexpected dead end | diff --git a/java/ql/test/kotlin/library-tests/exprs/exprs.ql b/java/ql/test/kotlin/library-tests/exprs/exprs.ql index 89eb09fc368..b39528a55e4 100644 --- a/java/ql/test/kotlin/library-tests/exprs/exprs.ql +++ b/java/ql/test/kotlin/library-tests/exprs/exprs.ql @@ -35,4 +35,5 @@ MaybeElement enclosingCallable(Expr e) { } from Expr e +where e.getFile().isSourceFile() select e, enclosingCallable(e), e.getPrimaryQlClasses() diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected index 81ea4c51841..b79725a80e3 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected @@ -43,41 +43,41 @@ memberRefExprs | samConversion.kt:5:27:5:31 | ...::... | samConversion.kt:5:27:5:31 | invoke | invoke(int,int) | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | | samConversion.kt:41:13:41:16 | ...::... | samConversion.kt:41:13:41:16 | invoke | invoke(java.lang.Object[]) | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | lambda_modifiers -| delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | override, public | -| funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | override, public | -| funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | override, public | -| funcExprs.kt:24:26:24:33 | ...->... | funcExprs.kt:24:26:24:33 | invoke | override, public | -| funcExprs.kt:25:29:25:38 | ...->... | funcExprs.kt:25:29:25:38 | invoke | override, public | -| funcExprs.kt:26:29:26:34 | ...->... | funcExprs.kt:26:29:26:34 | invoke | override, public | -| funcExprs.kt:27:29:27:42 | ...->... | funcExprs.kt:27:29:27:42 | invoke | override, public | -| funcExprs.kt:29:29:29:37 | ...->... | funcExprs.kt:29:29:29:37 | invoke | override, public | -| funcExprs.kt:30:28:30:50 | ...->... | funcExprs.kt:30:28:30:50 | invoke | override, public | -| funcExprs.kt:31:28:31:40 | ...->... | funcExprs.kt:31:28:31:40 | invoke | override, public | -| funcExprs.kt:32:28:32:44 | ...->... | funcExprs.kt:32:28:32:44 | invoke | override, public | -| funcExprs.kt:33:28:33:51 | ...->... | funcExprs.kt:33:28:33:51 | invoke | override, public | -| funcExprs.kt:33:37:33:47 | ...->... | funcExprs.kt:33:37:33:47 | invoke | override, public | -| funcExprs.kt:35:29:35:112 | ...->... | funcExprs.kt:35:29:35:112 | invoke | override, public | +| delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | final, override, public | +| funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | final, override, public | +| funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | final, override, public | +| funcExprs.kt:24:26:24:33 | ...->... | funcExprs.kt:24:26:24:33 | invoke | final, override, public | +| funcExprs.kt:25:29:25:38 | ...->... | funcExprs.kt:25:29:25:38 | invoke | final, override, public | +| funcExprs.kt:26:29:26:34 | ...->... | funcExprs.kt:26:29:26:34 | invoke | final, override, public | +| funcExprs.kt:27:29:27:42 | ...->... | funcExprs.kt:27:29:27:42 | invoke | final, override, public | +| funcExprs.kt:29:29:29:37 | ...->... | funcExprs.kt:29:29:29:37 | invoke | final, override, public | +| funcExprs.kt:30:28:30:50 | ...->... | funcExprs.kt:30:28:30:50 | invoke | final, override, public | +| funcExprs.kt:31:28:31:40 | ...->... | funcExprs.kt:31:28:31:40 | invoke | final, override, public | +| funcExprs.kt:32:28:32:44 | ...->... | funcExprs.kt:32:28:32:44 | invoke | final, override, public | +| funcExprs.kt:33:28:33:51 | ...->... | funcExprs.kt:33:28:33:51 | invoke | final, override, public | +| funcExprs.kt:33:37:33:47 | ...->... | funcExprs.kt:33:37:33:47 | invoke | final, override, public | +| funcExprs.kt:35:29:35:112 | ...->... | funcExprs.kt:35:29:35:112 | invoke | final, override, public | +| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | final, public | | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | override, public | -| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | public | -| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | override, public | -| funcExprs.kt:83:31:83:51 | ...->... | funcExprs.kt:83:31:83:51 | invoke | override, public | -| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend | +| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | final, override, public | +| funcExprs.kt:83:31:83:51 | ...->... | funcExprs.kt:83:31:83:51 | invoke | final, override, public | +| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:86:39:86:59 | invoke | final, override, public, suspend | +| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | final, public | | funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | override, public | -| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | public | -| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | -| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | override, public | -| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | override, public | -| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | override, public | -| samConversion.kt:9:33:11:5 | ...->... | samConversion.kt:9:33:11:5 | invoke | override, public | -| samConversion.kt:11:12:13:5 | ...->... | samConversion.kt:11:12:13:5 | invoke | override, public | +| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:94:15:94:67 | invoke | final, override, public, suspend | +| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | final, override, public | +| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | final, override, public | +| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | final, override, public | +| samConversion.kt:9:33:11:5 | ...->... | samConversion.kt:9:33:11:5 | invoke | final, override, public | +| samConversion.kt:11:12:13:5 | ...->... | samConversion.kt:11:12:13:5 | invoke | final, override, public | +| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | final, public | | samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | override, public | -| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public | -| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override, public | -| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | +| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | final, override, public | +| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | final, override, public, suspend | anon_class_member_modifiers | delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | get | override, public | | delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | invoke | override, public | -| delegatedProperties.kt:6:32:9:9 | new Function0(...) { ... } | delegatedProperties.kt:6:32:9:9 | invoke | override, public | +| delegatedProperties.kt:6:32:9:9 | new Function0(...) { ... } | delegatedProperties.kt:6:32:9:9 | invoke | final, override, public | | delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | | delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | | delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | invoke | override, public | @@ -86,8 +86,8 @@ anon_class_member_modifiers | delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | set | override, public | | delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | get | override, public | | delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | invoke | override, public | -| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | getCurValue | public | -| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | setCurValue | public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | getCurValue | final, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | setCurValue | final, public | | delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:27:22:27:88 | getValue | override, public | | delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:28:22:30:13 | setValue | override, public | | delegatedProperties.kt:33:27:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:27:33:47 | get | override, public | @@ -187,22 +187,22 @@ anon_class_member_modifiers | delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | get | override, public | | delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | invoke | override, public | | delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | set | override, public | -| exprs.kt:195:16:197:9 | new Interface1(...) { ... } | exprs.kt:196:13:196:49 | getA3 | public | -| funcExprs.kt:22:26:22:33 | new Function0(...) { ... } | funcExprs.kt:22:26:22:33 | invoke | override, public | -| funcExprs.kt:23:26:23:33 | new Function0(...) { ... } | funcExprs.kt:23:26:23:33 | invoke | override, public | -| funcExprs.kt:24:26:24:33 | new Function0(...) { ... } | funcExprs.kt:24:26:24:33 | invoke | override, public | -| funcExprs.kt:25:29:25:38 | new Function1(...) { ... } | funcExprs.kt:25:29:25:38 | invoke | override, public | -| funcExprs.kt:26:29:26:34 | new Function1(...) { ... } | funcExprs.kt:26:29:26:34 | invoke | override, public | -| funcExprs.kt:27:29:27:42 | new Function1(...) { ... } | funcExprs.kt:27:29:27:42 | invoke | override, public | -| funcExprs.kt:29:29:29:37 | new Function1(...) { ... } | funcExprs.kt:29:29:29:37 | invoke | override, public | -| funcExprs.kt:30:28:30:50 | new Function2(...) { ... } | funcExprs.kt:30:28:30:50 | invoke | override, public | -| funcExprs.kt:31:28:31:40 | new Function2(...) { ... } | funcExprs.kt:31:28:31:40 | invoke | override, public | -| funcExprs.kt:32:28:32:44 | new Function2(...) { ... } | funcExprs.kt:32:28:32:44 | invoke | override, public | -| funcExprs.kt:33:28:33:51 | new Function1>(...) { ... } | funcExprs.kt:33:28:33:51 | invoke | override, public | -| funcExprs.kt:33:37:33:47 | new Function1(...) { ... } | funcExprs.kt:33:37:33:47 | invoke | override, public | -| funcExprs.kt:35:29:35:112 | new Function22(...) { ... } | funcExprs.kt:35:29:35:112 | invoke | override, public | +| exprs.kt:195:16:197:9 | new Interface1(...) { ... } | exprs.kt:196:13:196:49 | getA3 | final, public | +| funcExprs.kt:22:26:22:33 | new Function0(...) { ... } | funcExprs.kt:22:26:22:33 | invoke | final, override, public | +| funcExprs.kt:23:26:23:33 | new Function0(...) { ... } | funcExprs.kt:23:26:23:33 | invoke | final, override, public | +| funcExprs.kt:24:26:24:33 | new Function0(...) { ... } | funcExprs.kt:24:26:24:33 | invoke | final, override, public | +| funcExprs.kt:25:29:25:38 | new Function1(...) { ... } | funcExprs.kt:25:29:25:38 | invoke | final, override, public | +| funcExprs.kt:26:29:26:34 | new Function1(...) { ... } | funcExprs.kt:26:29:26:34 | invoke | final, override, public | +| funcExprs.kt:27:29:27:42 | new Function1(...) { ... } | funcExprs.kt:27:29:27:42 | invoke | final, override, public | +| funcExprs.kt:29:29:29:37 | new Function1(...) { ... } | funcExprs.kt:29:29:29:37 | invoke | final, override, public | +| funcExprs.kt:30:28:30:50 | new Function2(...) { ... } | funcExprs.kt:30:28:30:50 | invoke | final, override, public | +| funcExprs.kt:31:28:31:40 | new Function2(...) { ... } | funcExprs.kt:31:28:31:40 | invoke | final, override, public | +| funcExprs.kt:32:28:32:44 | new Function2(...) { ... } | funcExprs.kt:32:28:32:44 | invoke | final, override, public | +| funcExprs.kt:33:28:33:51 | new Function1>(...) { ... } | funcExprs.kt:33:28:33:51 | invoke | final, override, public | +| funcExprs.kt:33:37:33:47 | new Function1(...) { ... } | funcExprs.kt:33:37:33:47 | invoke | final, override, public | +| funcExprs.kt:35:29:35:112 | new Function22(...) { ... } | funcExprs.kt:35:29:35:112 | invoke | final, override, public | +| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | final, public | | funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | override, public | -| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | public | | funcExprs.kt:38:26:38:38 | new Function0(...) { ... } | funcExprs.kt:38:26:38:38 | invoke | override, public | | funcExprs.kt:39:26:39:36 | new Function0(...) { ... } | funcExprs.kt:39:26:39:36 | invoke | override, public | | funcExprs.kt:40:29:40:41 | new Function1(...) { ... } | funcExprs.kt:40:29:40:41 | invoke | override, public | @@ -214,37 +214,37 @@ anon_class_member_modifiers | funcExprs.kt:46:30:46:41 | new FunctionN(...) { ... } | funcExprs.kt:46:30:46:41 | invoke | override, public | | funcExprs.kt:49:26:49:32 | new Function0(...) { ... } | funcExprs.kt:49:26:49:32 | invoke | override, public | | funcExprs.kt:51:8:51:16 | new Function0(...) { ... } | funcExprs.kt:51:8:51:16 | invoke | override, public | -| funcExprs.kt:75:12:75:22 | new Function1>,String>(...) { ... } | funcExprs.kt:75:12:75:22 | invoke | override, public | -| funcExprs.kt:83:31:83:51 | new Function1(...) { ... } | funcExprs.kt:83:31:83:51 | invoke | override, public | -| funcExprs.kt:86:39:86:59 | new Function1(...) { ... } | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend | +| funcExprs.kt:75:12:75:22 | new Function1>,String>(...) { ... } | funcExprs.kt:75:12:75:22 | invoke | final, override, public | +| funcExprs.kt:83:31:83:51 | new Function1(...) { ... } | funcExprs.kt:83:31:83:51 | invoke | final, override, public | +| funcExprs.kt:86:39:86:59 | new Function1(...) { ... } | funcExprs.kt:86:39:86:59 | invoke | final, override, public, suspend | +| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | final, public | | funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | override, public | -| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | public | -| funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | +| funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | funcExprs.kt:94:15:94:67 | invoke | final, override, public, suspend | | kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | kFunctionInvoke.kt:8:44:8:47 | invoke | override, public | -| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | override, public | -| samConversion.kt:2:31:2:45 | new Function1(...) { ... } | samConversion.kt:2:31:2:45 | invoke | override, public | -| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | override, public | -| samConversion.kt:4:27:4:42 | new Function2(...) { ... } | samConversion.kt:4:27:4:42 | invoke | override, public | -| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | override, public | +| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | final, override, public | +| samConversion.kt:2:31:2:45 | new Function1(...) { ... } | samConversion.kt:2:31:2:45 | invoke | final, override, public | +| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | final, override, public | +| samConversion.kt:4:27:4:42 | new Function2(...) { ... } | samConversion.kt:4:27:4:42 | invoke | final, override, public | +| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | final, override, public | | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | samConversion.kt:5:27:5:31 | invoke | override, public | -| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | override, public | -| samConversion.kt:7:29:7:46 | new Function2(...) { ... } | samConversion.kt:7:29:7:46 | invoke | override, public | -| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | override, public | -| samConversion.kt:9:33:11:5 | new Function1(...) { ... } | samConversion.kt:9:33:11:5 | invoke | override, public | -| samConversion.kt:11:12:13:5 | new Function1(...) { ... } | samConversion.kt:11:12:13:5 | invoke | override, public | +| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | final, override, public | +| samConversion.kt:7:29:7:46 | new Function2(...) { ... } | samConversion.kt:7:29:7:46 | invoke | final, override, public | +| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | final, override, public | +| samConversion.kt:9:33:11:5 | new Function1(...) { ... } | samConversion.kt:9:33:11:5 | invoke | final, override, public | +| samConversion.kt:11:12:13:5 | new Function1(...) { ... } | samConversion.kt:11:12:13:5 | invoke | final, override, public | | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | samConversion.kt:41:13:41:16 | invoke | override, public | -| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | override, public | -| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | override, public | +| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | final, override, public | +| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | final, override, public | +| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | final, public | | samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | override, public | -| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | public | -| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | override, public | -| samConversion.kt:46:32:46:44 | new Function1(...) { ... } | samConversion.kt:46:32:46:44 | invoke | override, public | -| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | override, public, suspend | -| samConversion.kt:58:30:58:45 | new Function2(...) { ... } | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | -| samConversion.kt:75:17:75:33 | new IntGetter(...) { ... } | samConversion.kt:75:17:75:33 | f | override, public | +| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | final, override, public | +| samConversion.kt:46:32:46:44 | new Function1(...) { ... } | samConversion.kt:46:32:46:44 | invoke | final, override, public | +| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | final, override, public, suspend | +| samConversion.kt:58:30:58:45 | new Function2(...) { ... } | samConversion.kt:58:30:58:45 | invoke | final, override, public, suspend | +| samConversion.kt:75:17:75:33 | new IntGetter(...) { ... } | samConversion.kt:75:17:75:33 | f | final, override, public | | samConversion.kt:75:27:75:32 | new KProperty0(...) { ... } | samConversion.kt:75:27:75:32 | get | override, public | | samConversion.kt:75:27:75:32 | new KProperty0(...) { ... } | samConversion.kt:75:27:75:32 | invoke | override, public | -| samConversion.kt:76:17:76:55 | new PropertyRefsGetter(...) { ... } | samConversion.kt:76:17:76:55 | f | override, public | +| samConversion.kt:76:17:76:55 | new PropertyRefsGetter(...) { ... } | samConversion.kt:76:17:76:55 | f | final, override, public | | samConversion.kt:76:36:76:54 | new KProperty1(...) { ... } | samConversion.kt:76:36:76:54 | get | override, public | | samConversion.kt:76:36:76:54 | new KProperty1(...) { ... } | samConversion.kt:76:36:76:54 | invoke | override, public | nonOverrideInvoke diff --git a/java/ql/test/kotlin/library-tests/generics-location/generics.kt b/java/ql/test/kotlin/library-tests/generics-location/generics.kt index 05ff48bc323..c269ceffea3 100644 --- a/java/ql/test/kotlin/library-tests/generics-location/generics.kt +++ b/java/ql/test/kotlin/library-tests/generics-location/generics.kt @@ -9,4 +9,3 @@ class B { val b1 = B() } } - diff --git a/java/ql/test/kotlin/library-tests/internal-constructor-called-from-java/test.kt b/java/ql/test/kotlin/library-tests/internal-constructor-called-from-java/test.kt index 905d9852632..65c8b43c44c 100644 --- a/java/ql/test/kotlin/library-tests/internal-constructor-called-from-java/test.kt +++ b/java/ql/test/kotlin/library-tests/internal-constructor-called-from-java/test.kt @@ -3,4 +3,3 @@ public class Test() { internal constructor(x: Int, y: Int) : this() { } } - diff --git a/java/ql/test/kotlin/library-tests/internal-public-alias/test.kt b/java/ql/test/kotlin/library-tests/internal-public-alias/test.kt index 216d3b3450d..e79e6d2f907 100644 --- a/java/ql/test/kotlin/library-tests/internal-public-alias/test.kt +++ b/java/ql/test/kotlin/library-tests/internal-public-alias/test.kt @@ -10,4 +10,3 @@ public class Test { internal fun internalFun() = 3 } - diff --git a/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected b/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected index 1f28867110e..378da6dd22f 100644 --- a/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected +++ b/java/ql/test/kotlin/library-tests/java_and_kotlin_internal/visibility.expected @@ -3,10 +3,14 @@ isInternal | Kotlin.kt:2:11:3:2 | kotlinFun$main | | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | modifiers_methods +| file://:0:0:0:0 | final | Kotlin.kt:2:11:3:2 | kotlinFun$main | +| file://:0:0:0:0 | final | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | | file://:0:0:0:0 | internal | Kotlin.kt:2:11:3:2 | kotlinFun$main | | file://:0:0:0:0 | internal | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | | file://:0:0:0:0 | static | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | #select +| Kotlin.kt:2:11:3:2 | kotlinFun$main | final | | Kotlin.kt:2:11:3:2 | kotlinFun$main | internal | +| Kotlin.kt:6:10:6:36 | topLevelKotlinFun | final | | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | internal | | Kotlin.kt:6:10:6:36 | topLevelKotlinFun | static | diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected index a1d0808d7a9..172aac49284 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected @@ -55,6 +55,8 @@ test.kt: # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null # 45| 4: [ExtensionMethod] testExtensionFunction +#-----| 1: (Annotations) +# 44| 1: [Annotation] JvmOverloads # 45| 3: [TypeAccess] int #-----| 4: (Parameters) # 45| 0: [Parameter] @@ -72,7 +74,7 @@ test.kt: # 45| 5: [BlockStmt] { ... } # 45| 0: [ReturnStmt] return ... # 45| 0: [VarAccess] a -# 45| 5: [Method] testExtensionFunction$default +# 45| 5: [ExtensionMethod] testExtensionFunction$default # 45| 3: [TypeAccess] int #-----| 4: (Parameters) # 45| 0: [Parameter] p0 @@ -116,7 +118,7 @@ test.kt: # 45| 2: [ReturnStmt] return ... # 45| 0: [MethodAccess] testExtensionFunction(...) # 45| -1: [TypeAccess] TestKt -# 45| 0: [VarAccess] p0 +# 45| 0: [ExtensionReceiverAccess] this # 45| 1: [VarAccess] p1 # 45| 2: [VarAccess] p2 # 45| 3: [VarAccess] p3 @@ -170,6 +172,9 @@ test.kt: # 1| 5: [IntegerLiteral] 23 # 1| 6: [NullLiteral] null # 6| 4: [Method] testStaticFunction +#-----| 1: (Annotations) +# 5| 1: [Annotation] JvmOverloads +# 5| 2: [Annotation] JvmStatic # 6| 3: [TypeAccess] int #-----| 4: (Parameters) # 6| 0: [Parameter] a @@ -277,6 +282,8 @@ test.kt: # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null # 9| 8: [Method] testMemberFunction +#-----| 1: (Annotations) +# 8| 1: [Annotation] JvmOverloads # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -356,9 +363,9 @@ test.kt: # 12| 0: [ReturnStmt] return ... # 12| 0: [MethodAccess] testMemberExtensionFunction$default(...) # 12| -1: [TypeAccess] Test -# 0| 0: [ExtensionReceiverAccess] this -# 0| 1: [ThisAccess] Test.this +# 0| 0: [ThisAccess] Test.this # 0| 0: [TypeAccess] Test +# 0| 1: [ExtensionReceiverAccess] this # 0| 2: [VarAccess] a # 1| 3: [NullLiteral] null # 0| 4: [VarAccess] c @@ -383,9 +390,9 @@ test.kt: # 12| 0: [ReturnStmt] return ... # 12| 0: [MethodAccess] testMemberExtensionFunction$default(...) # 12| -1: [TypeAccess] Test -# 0| 0: [ExtensionReceiverAccess] this -# 0| 1: [ThisAccess] Test.this +# 0| 0: [ThisAccess] Test.this # 0| 0: [TypeAccess] Test +# 0| 1: [ExtensionReceiverAccess] this # 0| 2: [VarAccess] a # 0| 3: [VarAccess] b # 0| 4: [VarAccess] c @@ -394,6 +401,8 @@ test.kt: # 1| 7: [IntegerLiteral] 23 # 1| 8: [NullLiteral] null # 12| 12: [ExtensionMethod] testMemberExtensionFunction +#-----| 1: (Annotations) +# 11| 1: [Annotation] JvmOverloads # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -411,13 +420,13 @@ test.kt: # 12| 5: [BlockStmt] { ... } # 12| 0: [ReturnStmt] return ... # 12| 0: [VarAccess] a -# 12| 13: [Method] testMemberExtensionFunction$default +# 12| 13: [ExtensionMethod] testMemberExtensionFunction$default # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] p0 -# 12| 0: [TypeAccess] Test2 -# 12| 1: [Parameter] p1 # 12| 0: [TypeAccess] Test +# 12| 1: [Parameter] p1 +# 12| 0: [TypeAccess] Test2 # 12| 2: [Parameter] p2 # 12| 0: [TypeAccess] int # 12| 3: [Parameter] p3 @@ -456,8 +465,8 @@ test.kt: # 12| 1: [FloatLiteral] 1.0 # 12| 2: [ReturnStmt] return ... # 12| 0: [MethodAccess] testMemberExtensionFunction(...) -# 12| -1: [VarAccess] p1 -# 12| 0: [VarAccess] p0 +# 12| -1: [VarAccess] p0 +# 12| 0: [ExtensionReceiverAccess] this # 12| 1: [VarAccess] p2 # 12| 2: [VarAccess] p3 # 12| 3: [VarAccess] p4 @@ -501,6 +510,8 @@ test.kt: # 1| 5: [IntegerLiteral] 23 # 1| 6: [NullLiteral] null # 16| 3: [Constructor] Test2 +#-----| 1: (Annotations) +# 16| 1: [Annotation] JvmOverloads #-----| 4: (Parameters) # 16| 0: [Parameter] a # 16| 0: [TypeAccess] int @@ -609,6 +620,8 @@ test.kt: # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null # 21| 4: [Method] testCompanionFunction +#-----| 1: (Annotations) +# 20| 1: [Annotation] JvmOverloads # 21| 3: [TypeAccess] int #-----| 4: (Parameters) # 21| 0: [Parameter] a @@ -718,6 +731,9 @@ test.kt: # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null # 24| 8: [Method] testStaticCompanionFunction +#-----| 1: (Annotations) +# 23| 1: [Annotation] JvmOverloads +# 23| 2: [Annotation] JvmStatic # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -883,6 +899,8 @@ test.kt: # 1| 4: [IntegerLiteral] 11 # 1| 5: [NullLiteral] null # 30| 3: [Constructor] GenericTest +#-----| 1: (Annotations) +# 30| 1: [Annotation] JvmOverloads #-----| 4: (Parameters) # 30| 0: [Parameter] a # 30| 0: [TypeAccess] int @@ -974,6 +992,8 @@ test.kt: # 1| 5: [IntegerLiteral] 11 # 1| 6: [NullLiteral] null # 33| 7: [Method] testMemberFunction +#-----| 1: (Annotations) +# 32| 1: [Annotation] JvmOverloads # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected index 00654e8929f..5fcccaca991 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected @@ -29,7 +29,7 @@ | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,float,boolean) | -| test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction$default | testMemberExtensionFunction$default(Test2,Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | +| test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction$default | testMemberExtensionFunction$default(Test,Test2,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,float,boolean) | diff --git a/java/ql/test/kotlin/library-tests/jvmstatic-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmstatic-annotation/PrintAst.expected index 3971afbe12b..338e67a33b0 100644 --- a/java/ql/test/kotlin/library-tests/jvmstatic-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmstatic-annotation/PrintAst.expected @@ -157,6 +157,8 @@ test.kt: # 17| 0: [KtInitializerAssignExpr] ...=... # 17| 0: [VarAccess] nonStaticProp # 13| 2: [Method] staticMethod +#-----| 1: (Annotations) +# 13| 1: [Annotation] JvmStatic # 13| 3: [TypeAccess] String #-----| 4: (Parameters) # 13| 0: [Parameter] s @@ -217,6 +219,8 @@ test.kt: # 17| -1: [ThisAccess] this # 17| 1: [VarAccess] # 20| 10: [Method] getPropWithStaticGetter +#-----| 1: (Annotations) +# 20| 1: [Annotation] JvmStatic # 20| 3: [TypeAccess] String # 20| 5: [BlockStmt] { ... } # 20| 0: [ReturnStmt] return ... @@ -239,6 +243,8 @@ test.kt: # 24| 0: [MethodAccess] getPropWithStaticGetter(...) # 24| -1: [ThisAccess] this # 25| 13: [Method] setPropWithStaticSetter +#-----| 1: (Annotations) +# 25| 1: [Annotation] JvmStatic # 25| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 25| 0: [Parameter] s @@ -307,6 +313,8 @@ test.kt: # 37| 0: [KtInitializerAssignExpr] ...=... # 37| 0: [VarAccess] nonStaticProp # 33| 2: [Method] staticMethod +#-----| 1: (Annotations) +# 33| 1: [Annotation] JvmStatic # 33| 3: [TypeAccess] String #-----| 4: (Parameters) # 33| 0: [Parameter] s @@ -370,6 +378,8 @@ test.kt: # 37| -1: [ThisAccess] this # 37| 1: [VarAccess] # 40| 10: [Method] getPropWithStaticGetter +#-----| 1: (Annotations) +# 40| 1: [Annotation] JvmStatic # 40| 3: [TypeAccess] String # 40| 5: [BlockStmt] { ... } # 40| 0: [ReturnStmt] return ... @@ -393,6 +403,8 @@ test.kt: # 44| 0: [MethodAccess] getPropWithStaticGetter(...) # 44| -1: [TypeAccess] NonCompanion # 45| 13: [Method] setPropWithStaticSetter +#-----| 1: (Annotations) +# 45| 1: [Annotation] JvmStatic # 45| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 45| 0: [Parameter] s diff --git a/java/ql/test/kotlin/library-tests/literals/literals.ql b/java/ql/test/kotlin/library-tests/literals/literals.ql index db19beff30b..587a71f3dc7 100644 --- a/java/ql/test/kotlin/library-tests/literals/literals.ql +++ b/java/ql/test/kotlin/library-tests/literals/literals.ql @@ -1,4 +1,5 @@ import java from Literal l +where l.getFile().isSourceFile() select l, l.getPrimaryQlClasses() diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 99315e33359..5de17a12bf9 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -293,12 +293,47 @@ | methods2.kt:8:5:9:5 | Unit | TypeAccess | | methods2.kt:8:27:8:32 | int | TypeAccess | | methods2.kt:8:35:8:40 | int | TypeAccess | -| methods3.kt:3:1:3:42 | Unit | TypeAccess | -| methods3.kt:3:5:3:7 | int | TypeAccess | -| methods3.kt:3:33:3:38 | int | TypeAccess | -| methods3.kt:6:5:6:46 | Unit | TypeAccess | -| methods3.kt:6:9:6:11 | int | TypeAccess | -| methods3.kt:6:37:6:42 | int | TypeAccess | +| methods3.kt:3:1:3:49 | 0 | IntegerLiteral | +| methods3.kt:3:1:3:49 | 1 | IntegerLiteral | +| methods3.kt:3:1:3:49 | ... & ... | AndBitwiseExpr | +| methods3.kt:3:1:3:49 | ... == ... | EQExpr | +| methods3.kt:3:1:3:49 | ...=... | AssignExpr | +| methods3.kt:3:1:3:49 | Methods3Kt | TypeAccess | +| methods3.kt:3:1:3:49 | Object | TypeAccess | +| methods3.kt:3:1:3:49 | String | TypeAccess | +| methods3.kt:3:1:3:49 | Unit | TypeAccess | +| methods3.kt:3:1:3:49 | Unit | TypeAccess | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt(...) | MethodAccess | +| methods3.kt:3:1:3:49 | int | TypeAccess | +| methods3.kt:3:1:3:49 | int | TypeAccess | +| methods3.kt:3:1:3:49 | p1 | VarAccess | +| methods3.kt:3:1:3:49 | p1 | VarAccess | +| methods3.kt:3:1:3:49 | p2 | VarAccess | +| methods3.kt:3:1:3:49 | this | ExtensionReceiverAccess | +| methods3.kt:3:5:3:10 | String | TypeAccess | +| methods3.kt:3:36:3:45 | int | TypeAccess | +| methods3.kt:3:45:3:45 | 1 | IntegerLiteral | +| methods3.kt:6:5:6:45 | 0 | IntegerLiteral | +| methods3.kt:6:5:6:45 | 1 | IntegerLiteral | +| methods3.kt:6:5:6:45 | ... & ... | AndBitwiseExpr | +| methods3.kt:6:5:6:45 | ... == ... | EQExpr | +| methods3.kt:6:5:6:45 | ...=... | AssignExpr | +| methods3.kt:6:5:6:45 | Class3 | TypeAccess | +| methods3.kt:6:5:6:45 | Object | TypeAccess | +| methods3.kt:6:5:6:45 | String | TypeAccess | +| methods3.kt:6:5:6:45 | Unit | TypeAccess | +| methods3.kt:6:5:6:45 | Unit | TypeAccess | +| methods3.kt:6:5:6:45 | fooBarMethodExt(...) | MethodAccess | +| methods3.kt:6:5:6:45 | int | TypeAccess | +| methods3.kt:6:5:6:45 | int | TypeAccess | +| methods3.kt:6:5:6:45 | p0 | VarAccess | +| methods3.kt:6:5:6:45 | p2 | VarAccess | +| methods3.kt:6:5:6:45 | p2 | VarAccess | +| methods3.kt:6:5:6:45 | p3 | VarAccess | +| methods3.kt:6:5:6:45 | this | ExtensionReceiverAccess | +| methods3.kt:6:9:6:14 | String | TypeAccess | +| methods3.kt:6:32:6:41 | int | TypeAccess | +| methods3.kt:6:41:6:41 | 1 | IntegerLiteral | | methods4.kt:7:5:7:34 | Unit | TypeAccess | | methods4.kt:7:11:7:29 | InsideNestedTest | TypeAccess | | methods5.kt:3:1:11:1 | Unit | TypeAccess | diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.ql b/java/ql/test/kotlin/library-tests/methods/exprs.ql index 6ded7c0026d..c2ae4f55ac7 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.ql +++ b/java/ql/test/kotlin/library-tests/methods/exprs.ql @@ -1,4 +1,5 @@ import java from Expr e +where e.getFile().isSourceFile() select e, e.getPrimaryQlClasses() diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index 6a86ea6bf5b..89cdd03f303 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -1,59 +1,61 @@ methods | clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:0:0:0:0 | | () | static | Compiler generated | -| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | getTopLevelInt | getTopLevelInt() | public, static | Compiler generated | -| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | setTopLevelInt | setTopLevelInt(int) | public, static | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component1 | component1() | public | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component2 | component2() | public | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy | copy(int,java.lang.String) | public | Compiler generated | +| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | getTopLevelInt | getTopLevelInt() | final, public, static | Compiler generated | +| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | setTopLevelInt | setTopLevelInt(int) | final, public, static | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component1 | component1() | final, public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component2 | component2() | final, public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy | copy(int,java.lang.String) | final, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy$default | copy$default(DataClass,int,java.lang.String,int,java.lang.Object) | public, static | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | equals | equals(java.lang.Object) | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | hashCode | hashCode() | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | toString | toString() | override, public | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:22:1:31 | getX | getX() | public | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | getY | getY() | public | Compiler generated | -| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | setY | setY(java.lang.String) | public | Compiler generated | -| delegates.kt:3:1:12:1 | MyClass | delegates.kt:4:18:6:5 | getLazyProp | getLazyProp() | public | Compiler generated | -| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:32:11:5 | getObservableProp | getObservableProp() | public | Compiler generated | -| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:32:11:5 | setObservableProp | setObservableProp(java.lang.String) | public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:22:1:31 | getX | getX() | final, public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | getY | getY() | final, public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | setY | setY(java.lang.String) | final, public | Compiler generated | +| delegates.kt:3:1:12:1 | MyClass | delegates.kt:4:18:6:5 | getLazyProp | getLazyProp() | final, public | Compiler generated | +| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:32:11:5 | getObservableProp | getObservableProp() | final, public | Compiler generated | +| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:32:11:5 | setObservableProp | setObservableProp(java.lang.String) | final, public | Compiler generated | | delegates.kt:4:18:6:5 | new KProperty1(...) { ... } | delegates.kt:4:18:6:5 | get | get(MyClass) | override, public | | | delegates.kt:4:18:6:5 | new KProperty1(...) { ... } | delegates.kt:4:18:6:5 | invoke | invoke(MyClass) | override, public | | -| delegates.kt:4:26:6:5 | new Function0(...) { ... } | delegates.kt:4:26:6:5 | invoke | invoke() | override, public | | +| delegates.kt:4:26:6:5 | new Function0(...) { ... } | delegates.kt:4:26:6:5 | invoke | invoke() | final, override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | get | get(MyClass) | override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | get | get(MyClass) | override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | invoke | invoke(MyClass) | override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | invoke | invoke(MyClass) | override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | set | set(MyClass,java.lang.String) | override, public | | | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | set | set(MyClass,java.lang.String) | override, public | | -| delegates.kt:8:66:11:5 | new Function3,String,String,Unit>(...) { ... } | delegates.kt:8:66:11:5 | invoke | invoke(kotlin.reflect.KProperty,java.lang.String,java.lang.String) | override, public | | +| delegates.kt:8:66:11:5 | new Function3,String,String,Unit>(...) { ... } | delegates.kt:8:66:11:5 | invoke | invoke(kotlin.reflect.KProperty,java.lang.String,java.lang.String) | final, override, public | | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | | () | static | Compiler generated | -| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | -| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | -| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:22:1:31 | getV | getV() | public | Compiler generated | +| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | final, public, static | Compiler generated | +| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | values | values() | final, public, static | Compiler generated | +| enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:22:1:31 | getV | getV() | final, public | Compiler generated | | enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | | () | static | Compiler generated | -| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | -| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | -| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:13:12:13:29 | f | f(int) | public | | -| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:14:12:14:29 | g | g(int) | public | | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | final, public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | values | values() | final, public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:13:12:13:29 | f | f(int) | abstract, public | | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:14:12:14:29 | g | g(int) | abstract, public | | | enumClass.kt:8:3:11:4 | VAL | enumClass.kt:9:14:9:30 | f | f(int) | override, public | | | enumClass.kt:8:3:11:4 | VAL | enumClass.kt:10:14:10:42 | g | g(int) | override, public | | -| methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | public, static | | -| methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | public | | -| methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public, static | | -| methods3.kt:5:1:7:1 | Class3 | methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public | | -| methods4.kt:5:3:9:3 | InsideNestedTest | methods4.kt:7:5:7:34 | m | m(foo.bar.NestedTest.InsideNestedTest) | public | | -| methods5.kt:0:0:0:0 | Methods5Kt | methods5.kt:3:1:11:1 | x | x() | public, static | | -| methods5.kt:5:3:5:27 | | methods5.kt:5:3:5:27 | a | a(int) | public | | -| methods5.kt:9:3:9:32 | | methods5.kt:9:3:9:32 | f1 | f1(foo.bar.C1,int) | public | | -| methods6.kt:0:0:0:0 | Methods6Kt | methods6.kt:3:9:4:1 | s | s() | public, static, suspend | | -| methods.kt:0:0:0:0 | MethodsKt | methods.kt:2:1:3:1 | topLevelMethod | topLevelMethod(int,int) | public, static | | -| methods.kt:5:1:20:1 | Class | methods.kt:6:5:7:5 | classMethod | classMethod(int,int) | public | | -| methods.kt:5:1:20:1 | Class | methods.kt:9:5:12:5 | anotherClassMethod | anotherClassMethod(int,int) | public | | -| methods.kt:5:1:20:1 | Class | methods.kt:14:12:14:29 | publicFun | publicFun() | public | | -| methods.kt:5:1:20:1 | Class | methods.kt:15:15:15:35 | protectedFun | protectedFun() | protected | | -| methods.kt:5:1:20:1 | Class | methods.kt:16:13:16:31 | privateFun | privateFun() | private | | -| methods.kt:5:1:20:1 | Class | methods.kt:17:14:17:33 | internalFun$main | internalFun$main() | internal | | -| methods.kt:5:1:20:1 | Class | methods.kt:18:5:18:36 | noExplicitVisibilityFun | noExplicitVisibilityFun() | public | | -| methods.kt:5:1:20:1 | Class | methods.kt:19:12:19:29 | inlineFun | inlineFun() | inline, public | | +| methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | final, public, static | | +| methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | final, public | | +| methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(java.lang.String,int) | final, public, static | | +| methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | fooBarTopLevelMethodExt$default(java.lang.String,int,int,java.lang.Object) | public, static | Compiler generated | +| methods3.kt:5:1:7:1 | Class3 | methods3.kt:6:5:6:45 | fooBarMethodExt | fooBarMethodExt(java.lang.String,int) | final, public | | +| methods3.kt:5:1:7:1 | Class3 | methods3.kt:6:5:6:45 | fooBarMethodExt$default | fooBarMethodExt$default(foo.bar.Class3,java.lang.String,int,int,java.lang.Object) | public, static | Compiler generated | +| methods4.kt:5:3:9:3 | InsideNestedTest | methods4.kt:7:5:7:34 | m | m(foo.bar.NestedTest.InsideNestedTest) | final, public | | +| methods5.kt:0:0:0:0 | Methods5Kt | methods5.kt:3:1:11:1 | x | x() | final, public, static | | +| methods5.kt:5:3:5:27 | | methods5.kt:5:3:5:27 | a | a(int) | final, public | | +| methods5.kt:9:3:9:32 | | methods5.kt:9:3:9:32 | f1 | f1(foo.bar.C1,int) | final, public | | +| methods6.kt:0:0:0:0 | Methods6Kt | methods6.kt:3:9:4:1 | s | s() | final, public, static, suspend | | +| methods.kt:0:0:0:0 | MethodsKt | methods.kt:2:1:3:1 | topLevelMethod | topLevelMethod(int,int) | final, public, static | | +| methods.kt:5:1:20:1 | Class | methods.kt:6:5:7:5 | classMethod | classMethod(int,int) | final, public | | +| methods.kt:5:1:20:1 | Class | methods.kt:9:5:12:5 | anotherClassMethod | anotherClassMethod(int,int) | final, public | | +| methods.kt:5:1:20:1 | Class | methods.kt:14:12:14:29 | publicFun | publicFun() | final, public | | +| methods.kt:5:1:20:1 | Class | methods.kt:15:15:15:35 | protectedFun | protectedFun() | final, protected | | +| methods.kt:5:1:20:1 | Class | methods.kt:16:13:16:31 | privateFun | privateFun() | final, private | | +| methods.kt:5:1:20:1 | Class | methods.kt:17:14:17:33 | internalFun$main | internalFun$main() | final, internal | | +| methods.kt:5:1:20:1 | Class | methods.kt:18:5:18:36 | noExplicitVisibilityFun | noExplicitVisibilityFun() | final, public | | +| methods.kt:5:1:20:1 | Class | methods.kt:19:12:19:29 | inlineFun | inlineFun() | final, inline, public | | constructors | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:6:1:47 | DataClass | DataClass(int,java.lang.String) | | delegates.kt:3:1:12:1 | MyClass | delegates.kt:3:1:12:1 | MyClass | MyClass() | @@ -74,6 +76,15 @@ constructors | methods5.kt:13:1:13:14 | C1 | methods5.kt:13:1:13:14 | C1 | C1() | | methods.kt:5:1:20:1 | Class | methods.kt:5:1:20:1 | Class | Class() | extensions -| methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | file://:0:0:0:0 | int | -| methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | file://:0:0:0:0 | int | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:6:5:6:45 | fooBarMethodExt | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | | methods5.kt:9:3:9:32 | f1 | file:///!unknown-binary-location/foo/bar/C1.class:0:0:0:0 | C1 | +extensionsMismatch +extensionIndex +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | 0 | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | 0 | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:6:5:6:45 | fooBarMethodExt | 0 | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | 1 | file:///modules/java.base/java/lang/String.class:0:0:0:0 | String | +| methods5.kt:9:3:9:32 | f1 | 0 | file:///!unknown-binary-location/foo/bar/C1.class:0:0:0:0 | C1 | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.ql b/java/ql/test/kotlin/library-tests/methods/methods.ql index 365d41ff1ee..0f0b43f4e4b 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.ql +++ b/java/ql/test/kotlin/library-tests/methods/methods.ql @@ -17,3 +17,19 @@ query predicate constructors(RefType declType, Constructor c, string signature) } query predicate extensions(ExtensionMethod m, Type t) { m.getExtendedType() = t and m.fromSource() } + +query predicate extensionsMismatch(Method src, Method def) { + src.getKotlinParameterDefaultsProxy() = def and + ( + src instanceof ExtensionMethod and not def instanceof ExtensionMethod + or + def instanceof ExtensionMethod and not src instanceof ExtensionMethod + ) +} + +query predicate extensionIndex(ExtensionMethod m, int i, Type t) { + m.fromSource() and + m.getExtensionReceiverParameterIndex() = i and + m.getExtendedType() = t and + m.getParameter(i).getType() = t +} diff --git a/java/ql/test/kotlin/library-tests/methods/methods3.kt b/java/ql/test/kotlin/library-tests/methods/methods3.kt index fdd759a7840..120a5339a5a 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods3.kt +++ b/java/ql/test/kotlin/library-tests/methods/methods3.kt @@ -1,7 +1,7 @@ package foo.bar -fun Int.fooBarTopLevelMethodExt(x: Int) {} +fun String.fooBarTopLevelMethodExt(x: Int = 1) {} class Class3 { - fun Int.fooBarTopLevelMethodExt(x: Int) {} + fun String.fooBarMethodExt(x: Int = 1) {} } diff --git a/java/ql/test/kotlin/library-tests/methods/parameters.expected b/java/ql/test/kotlin/library-tests/methods/parameters.expected index 4475aeba459..d4b3a2e2411 100644 --- a/java/ql/test/kotlin/library-tests/methods/parameters.expected +++ b/java/ql/test/kotlin/library-tests/methods/parameters.expected @@ -32,10 +32,19 @@ | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:34:4:39 | y | 1 | | methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:27:8:32 | x | 0 | | methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:35:8:40 | y | 1 | -| methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | methods3.kt:3:5:3:7 | | 0 | -| methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | methods3.kt:3:33:3:38 | x | 1 | -| methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | methods3.kt:6:9:6:11 | | 0 | -| methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | methods3.kt:6:37:6:42 | x | 1 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | methods3.kt:3:5:3:10 | | 0 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | methods3.kt:3:36:3:45 | x | 1 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | methods3.kt:3:1:3:49 | p0 | 0 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | methods3.kt:3:1:3:49 | p1 | 1 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | methods3.kt:3:1:3:49 | p2 | 2 | +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | methods3.kt:3:1:3:49 | p3 | 3 | +| methods3.kt:6:5:6:45 | fooBarMethodExt | methods3.kt:6:9:6:14 | | 0 | +| methods3.kt:6:5:6:45 | fooBarMethodExt | methods3.kt:6:32:6:41 | x | 1 | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | methods3.kt:6:5:6:45 | p0 | 0 | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | methods3.kt:6:5:6:45 | p1 | 1 | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | methods3.kt:6:5:6:45 | p2 | 2 | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | methods3.kt:6:5:6:45 | p3 | 3 | +| methods3.kt:6:5:6:45 | fooBarMethodExt$default | methods3.kt:6:5:6:45 | p4 | 4 | | methods4.kt:7:5:7:34 | m | methods4.kt:7:11:7:29 | x | 0 | | methods5.kt:5:3:5:27 | a | methods5.kt:5:13:5:18 | i | 0 | | methods5.kt:9:3:9:32 | f1 | methods5.kt:9:12:9:17 | | 0 | diff --git a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected index 1a8613b00cc..045fdb6d21c 100644 --- a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected +++ b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected @@ -3,18 +3,22 @@ | modifiers.kt:2:5:2:21 | a | Field | final | | modifiers.kt:2:5:2:21 | a | Field | private | | modifiers.kt:2:5:2:21 | a | Property | private | +| modifiers.kt:2:13:2:21 | getA$private | Method | final | | modifiers.kt:2:13:2:21 | getA$private | Method | private | | modifiers.kt:3:5:3:23 | b | Field | final | | modifiers.kt:3:5:3:23 | b | Field | private | | modifiers.kt:3:5:3:23 | b | Property | protected | +| modifiers.kt:3:15:3:23 | getB | Method | final | | modifiers.kt:3:15:3:23 | getB | Method | protected | | modifiers.kt:4:5:4:22 | c | Field | final | | modifiers.kt:4:5:4:22 | c | Field | private | | modifiers.kt:4:5:4:22 | c | Property | internal | +| modifiers.kt:4:14:4:22 | getC$main | Method | final | | modifiers.kt:4:14:4:22 | getC$main | Method | internal | | modifiers.kt:5:5:5:34 | d | Field | final | | modifiers.kt:5:5:5:34 | d | Field | private | | modifiers.kt:5:5:5:34 | d | Property | public | +| modifiers.kt:5:5:5:34 | getD | Method | final | | modifiers.kt:5:5:5:34 | getD | Method | public | | modifiers.kt:7:5:9:5 | Nested | Class | final | | modifiers.kt:7:5:9:5 | Nested | Class | protected | @@ -22,29 +26,38 @@ | modifiers.kt:8:9:8:29 | e | Field | final | | modifiers.kt:8:9:8:29 | e | Field | private | | modifiers.kt:8:9:8:29 | e | Property | public | +| modifiers.kt:8:16:8:29 | getE | Method | final | | modifiers.kt:8:16:8:29 | getE | Method | public | +| modifiers.kt:11:5:15:5 | fn1 | Method | final | | modifiers.kt:11:5:15:5 | fn1 | Method | public | | modifiers.kt:12:16:14:9 | | Constructor | public | | modifiers.kt:12:16:14:9 | new Object(...) { ... } | AnonymousClass | final | | modifiers.kt:12:16:14:9 | new Object(...) { ... } | AnonymousClass | private | | modifiers.kt:12:16:14:9 | new Object(...) { ... } | LocalClass | final | | modifiers.kt:12:16:14:9 | new Object(...) { ... } | LocalClass | private | +| modifiers.kt:13:13:13:23 | fn | Method | final | | modifiers.kt:13:13:13:23 | fn | Method | public | +| modifiers.kt:17:5:20:5 | fn2 | Method | final | | modifiers.kt:17:5:20:5 | fn2 | Method | public | | modifiers.kt:18:9:18:24 | | Constructor | public | | modifiers.kt:18:9:18:24 | | LocalClass | final | | modifiers.kt:18:9:18:24 | | LocalClass | private | +| modifiers.kt:18:9:18:24 | fnLocal | Method | final | | modifiers.kt:18:9:18:24 | fnLocal | Method | public | +| modifiers.kt:22:5:24:5 | fn3 | Method | final | | modifiers.kt:22:5:24:5 | fn3 | Method | public | | modifiers.kt:23:9:23:27 | localClass | Constructor | public | | modifiers.kt:23:9:23:27 | localClass | LocalClass | final | | modifiers.kt:23:9:23:27 | localClass | LocalClass | private | +| modifiers.kt:26:12:26:46 | fn4 | Method | final | | modifiers.kt:26:12:26:46 | fn4 | Method | inline | | modifiers.kt:26:12:26:46 | fn4 | Method | public | | modifiers.kt:26:20:26:41 | f | Parameter | noinline | +| modifiers.kt:27:12:27:49 | fn5 | Method | final | | modifiers.kt:27:12:27:49 | fn5 | Method | inline | | modifiers.kt:27:12:27:49 | fn5 | Method | public | | modifiers.kt:27:20:27:44 | f | Parameter | crossinline | +| modifiers.kt:28:12:28:39 | fn6 | Method | final | | modifiers.kt:28:12:28:39 | fn6 | Method | inline | | modifiers.kt:28:12:28:39 | fn6 | Method | public | | modifiers.kt:28:17:28:25 | T | TypeVariable | reified | @@ -57,6 +70,7 @@ | modifiers.kt:31:1:33:1 | Y | ParameterizedType | public | | modifiers.kt:31:9:31:13 | T1 | TypeVariable | in | | modifiers.kt:31:16:31:21 | T2 | TypeVariable | out | +| modifiers.kt:32:5:32:32 | foo | Method | final | | modifiers.kt:32:5:32:32 | foo | Method | public | | modifiers.kt:35:1:41:1 | LateInit | Class | final | | modifiers.kt:35:1:41:1 | LateInit | Class | public | @@ -64,7 +78,10 @@ | modifiers.kt:36:5:36:40 | test0 | Field | private | | modifiers.kt:36:5:36:40 | test0 | Property | lateinit | | modifiers.kt:36:5:36:40 | test0 | Property | private | +| modifiers.kt:36:22:36:40 | getTest0$private | Method | final | | modifiers.kt:36:22:36:40 | getTest0$private | Method | private | +| modifiers.kt:36:22:36:40 | setTest0$private | Method | final | | modifiers.kt:36:22:36:40 | setTest0$private | Method | private | +| modifiers.kt:38:5:40:5 | fn | Method | final | | modifiers.kt:38:5:40:5 | fn | Method | public | | modifiers.kt:39:22:39:26 | LateInit test1 | LocalVariableDecl | lateinit | diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 972e826cdca..13bd441dfcd 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -525,13 +525,13 @@ test.kt: # 21| 0: [MethodAccess] sink(...) # 21| -1: [TypeAccess] TestKt # 21| 0: [VarAccess] y -# 19| 3: [Method] f$default +# 19| 3: [ExtensionMethod] f$default # 19| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 19| 0: [Parameter] p0 -# 19| 0: [TypeAccess] String -# 19| 1: [Parameter] p1 # 19| 0: [TypeAccess] TestExtensionMember +# 19| 1: [Parameter] p1 +# 19| 0: [TypeAccess] String # 19| 2: [Parameter] p2 # 19| 0: [TypeAccess] String # 19| 3: [Parameter] p3 @@ -565,8 +565,8 @@ test.kt: # 19| 1: [StringLiteral] "hello world" # 19| 2: [ReturnStmt] return ... # 19| 0: [MethodAccess] f(...) -# 19| -1: [VarAccess] p1 -# 19| 0: [VarAccess] p0 +# 19| -1: [VarAccess] p0 +# 19| 0: [ExtensionReceiverAccess] this # 19| 1: [VarAccess] p2 # 19| 2: [VarAccess] p3 # 19| 3: [VarAccess] p4 @@ -579,8 +579,8 @@ test.kt: # 25| 0: [ExprStmt] ; # 25| 0: [MethodAccess] f$default(...) # 25| -1: [TypeAccess] TestExtensionMember -# 25| 0: [VarAccess] sunk -# 25| 1: [ThisAccess] this +# 25| 0: [ThisAccess] this +# 25| 1: [VarAccess] sunk # 25| 2: [StringLiteral] "extension sunk" # 1| 3: [NullLiteral] null # 1| 4: [NullLiteral] null @@ -589,8 +589,8 @@ test.kt: # 26| 1: [ExprStmt] ; # 26| 0: [MethodAccess] f$default(...) # 26| -1: [TypeAccess] TestExtensionMember -# 26| 0: [VarAccess] sunk -# 26| 1: [ThisAccess] this +# 26| 0: [ThisAccess] this +# 26| 1: [VarAccess] sunk # 26| 2: [StringLiteral] "extension sunk fp" # 26| 3: [StringLiteral] "extension sunk 2" # 1| 4: [NullLiteral] null @@ -609,6 +609,8 @@ test.kt: # 32| 0: [SuperConstructorInvocationStmt] super(...) # 32| 1: [BlockStmt] { ... } # 34| 2: [Method] f +#-----| 1: (Annotations) +# 34| 1: [Annotation] JvmStatic # 34| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 34| 0: [Parameter] x @@ -729,13 +731,13 @@ test.kt: # 57| 0: [MethodAccess] sink(...) # 57| -1: [TypeAccess] TestKt # 57| 0: [VarAccess] y -# 56| 4: [Method] test$default +# 56| 4: [ExtensionMethod] test$default # 56| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 56| 0: [Parameter] p0 -# 56| 0: [TypeAccess] ExtendMe -# 56| 1: [Parameter] p1 # 56| 0: [TypeAccess] TestReceiverReferences +# 56| 1: [Parameter] p1 +# 56| 0: [TypeAccess] ExtendMe # 56| 2: [Parameter] p2 # 56| 0: [TypeAccess] String # 56| 3: [Parameter] p3 @@ -759,7 +761,7 @@ test.kt: # 56| 1: [MethodAccess] f(...) # 56| -1: [VarAccess] p0 # 56| 0: [MethodAccess] g(...) -# 56| -1: [VarAccess] p1 +# 56| -1: [VarAccess] p0 # 56| 0: [VarAccess] p2 # 56| 1: [IfStmt] if (...) # 56| 0: [EQExpr] ... == ... @@ -773,8 +775,8 @@ test.kt: # 56| 1: [StringLiteral] "hello world" # 56| 2: [ReturnStmt] return ... # 56| 0: [MethodAccess] test(...) -# 56| -1: [VarAccess] p1 -# 56| 0: [VarAccess] p0 +# 56| -1: [VarAccess] p0 +# 56| 0: [ExtensionReceiverAccess] this # 56| 1: [VarAccess] p2 # 56| 2: [VarAccess] p3 # 56| 3: [VarAccess] p4 @@ -787,8 +789,8 @@ test.kt: # 61| 0: [ExprStmt] ; # 61| 0: [MethodAccess] test$default(...) # 61| -1: [TypeAccess] TestReceiverReferences -# 61| 0: [VarAccess] t -# 61| 1: [ThisAccess] this +# 61| 0: [ThisAccess] this +# 61| 1: [VarAccess] t # 61| 2: [StringLiteral] "receiver refs sunk" # 1| 3: [NullLiteral] null # 1| 4: [NullLiteral] null @@ -797,8 +799,8 @@ test.kt: # 62| 1: [ExprStmt] ; # 62| 0: [MethodAccess] test$default(...) # 62| -1: [TypeAccess] TestReceiverReferences -# 62| 0: [VarAccess] t -# 62| 1: [ThisAccess] this +# 62| 0: [ThisAccess] this +# 62| 1: [VarAccess] t # 62| 2: [StringLiteral] "receiver refs sunk fp" # 62| 3: [StringLiteral] "receiver refs sunk 2" # 1| 4: [NullLiteral] null diff --git a/java/ql/test/kotlin/library-tests/reflection/PrintAst.expected b/java/ql/test/kotlin/library-tests/reflection/PrintAst.expected index c46be5c7900..9f4ece3d033 100644 --- a/java/ql/test/kotlin/library-tests/reflection/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/reflection/PrintAst.expected @@ -534,7 +534,7 @@ reflection.kt: # 150| 0: [AddExpr] ... + ... # 150| 0: [VarAccess] x # 150| 1: [VarAccess] y -# 150| 20: [Method] extTakesOptionalParam$default +# 150| 20: [ExtensionMethod] extTakesOptionalParam$default # 150| 3: [TypeAccess] int #-----| 4: (Parameters) # 150| 0: [Parameter] p0 @@ -561,7 +561,7 @@ reflection.kt: # 150| 1: [ReturnStmt] return ... # 150| 0: [MethodAccess] extTakesOptionalParam(...) # 150| -1: [TypeAccess] ReflectionKt -# 150| 0: [VarAccess] p0 +# 150| 0: [ExtensionReceiverAccess] this # 150| 1: [VarAccess] p1 # 150| 2: [VarAccess] p2 # 152| 21: [Method] extensionAdaptedParams diff --git a/java/ql/test/kotlin/library-tests/stmts/exprs.ql b/java/ql/test/kotlin/library-tests/stmts/exprs.ql index 6ded7c0026d..c2ae4f55ac7 100644 --- a/java/ql/test/kotlin/library-tests/stmts/exprs.ql +++ b/java/ql/test/kotlin/library-tests/stmts/exprs.ql @@ -1,4 +1,5 @@ import java from Expr e +where e.getFile().isSourceFile() select e, e.getPrimaryQlClasses() diff --git a/java/ql/test/kotlin/library-tests/variables/variableAccesses.ql b/java/ql/test/kotlin/library-tests/variables/variableAccesses.ql index 0fa6d19d142..2d6622d032c 100644 --- a/java/ql/test/kotlin/library-tests/variables/variableAccesses.ql +++ b/java/ql/test/kotlin/library-tests/variables/variableAccesses.ql @@ -1,6 +1,6 @@ import java -query predicate varAcc(VarAccess va) { any() } +query predicate varAcc(VarAccess va) { va.getFile().isSourceFile() } query predicate extensionReceiverAcc(ExtensionReceiverAccess va) { any() } diff --git a/java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref b/java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref deleted file mode 100644 index c24d124c0b2..00000000000 --- a/java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref +++ /dev/null @@ -1 +0,0 @@ -utils/model-generator/CaptureNegativeSummaryModels.ql \ No newline at end of file diff --git a/java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected b/java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.expected similarity index 100% rename from java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected rename to java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.expected diff --git a/java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref b/java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref new file mode 100644 index 00000000000..cb6ef7faa65 --- /dev/null +++ b/java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref @@ -0,0 +1 @@ +utils/model-generator/CaptureNeutralModels.ql \ No newline at end of file diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index c372cf58f0a..e08bc766fc5 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-lib description: CodeQL libraries for the experimental ML-powered queries -version: 0.4.3 +version: 0.4.4 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index a448b0e29d3..9eeb2a03fd8 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/javascript-experimental-atm-queries description: Experimental ML-powered queries for JavaScript language: javascript -version: 0.4.3 +version: 0.4.4 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: diff --git a/javascript/ql/lib/javascript.qll b/javascript/ql/lib/javascript.qll index 982ddae9128..53bb91797aa 100644 --- a/javascript/ql/lib/javascript.qll +++ b/javascript/ql/lib/javascript.qll @@ -99,7 +99,6 @@ import semmle.javascript.frameworks.JWT import semmle.javascript.frameworks.Handlebars import semmle.javascript.frameworks.History import semmle.javascript.frameworks.Immutable -import semmle.javascript.frameworks.ImportGeneratedModels import semmle.javascript.frameworks.Knex import semmle.javascript.frameworks.LazyCache import semmle.javascript.frameworks.LdapJS diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index eeb58f1d25a..55e4fcf869f 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -7,3 +7,5 @@ library: true upgrades: upgrades dependencies: codeql/regex: ${workspace} +dataExtensions: + - semmle/javascript/frameworks/**/model.yml diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ImportGeneratedModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/ImportGeneratedModels.qll deleted file mode 100644 index ffb7ab60fba..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/ImportGeneratedModels.qll +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Imports all generated models. - */ - -private import minimongo.Model -private import mongodb.Model -private import mssql.Model -private import mysql.Model -private import pg.Model -private import sequelize.Model -private import spanner.Model -private import sqlite3.Model diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll index 0e744ba801a..1b7e8cb326a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll @@ -72,6 +72,7 @@ private module API = Specific::API; private module DataFlow = Specific::DataFlow; private import Specific::AccessPathSyntax +private import ApiGraphModelsExtensions as Extensions /** Module containing hooks for providing input data to be interpreted as a model. */ module ModelInput { @@ -236,6 +237,8 @@ predicate sourceModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sourceModel(type, path, kind) } /** Holds if a sink model exists for the given parameters. */ @@ -246,6 +249,8 @@ private predicate sinkModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sinkModel(type, path, kind) } /** Holds if a summary model `row` exists for the given parameters. */ @@ -258,6 +263,8 @@ private predicate summaryModel(string type, string path, string input, string ou row.splitAt(";", 3) = output and row.splitAt(";", 4) = kind ) + or + Extensions::summaryModel(type, path, input, output, kind) } /** Holds if a type model exists for the given parameters. */ @@ -268,6 +275,8 @@ private predicate typeModel(string type1, string type2, string path) { row.splitAt(";", 1) = type2 and row.splitAt(";", 2) = path ) + or + Extensions::typeModel(type1, type2, path) } /** Holds if a type variable model exists for the given parameters. */ @@ -277,6 +286,8 @@ private predicate typeVariableModel(string name, string path) { row.splitAt(";", 0) = name and row.splitAt(";", 1) = path ) + or + Extensions::typeVariableModel(name, path) } /** diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll new file mode 100644 index 00000000000..11c3bb9657e --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -0,0 +1,36 @@ +/** + * Defines extensible predicates for contributing library models from data extensions. + */ + +/** + * Holds if the value at `(type, path)` should be seen as a flow + * source of the given `kind`. + * + * The kind `remote` represents a general remote flow source. + */ +extensible predicate sourceModel(string type, string path, string kind); + +/** + * Holds if the value at `(type, path)` should be seen as a sink + * of the given `kind`. + */ +extensible predicate sinkModel(string type, string path, string kind); + +/** + * Holds if calls to `(type, path)`, the value referred to by `input` + * can flow to the value referred to by `output`. + * + * `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps, + * respectively. + */ +extensible predicate summaryModel(string type, string path, string input, string output, string kind); + +/** + * Holds if `(type2, path)` should be seen as an instance of `type1`. + */ +extensible predicate typeModel(string type1, string type2, string path); + +/** + * Holds if `path` can be substituted for a token `TypeVar[name]`. + */ +extensible predicate typeVariableModel(string name, string path); diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/model.yml new file mode 100644 index 00000000000..634a1bb3f8b --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/model.yml @@ -0,0 +1,26 @@ +extensions: + # Contribute empty data sets to avoid errors about an undefined extensionals + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: [] + + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: [] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: [] + + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: [] + + - addsTo: + pack: codeql/javascript-all + extensible: typeVariableModel + data: [] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/minimongo/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/minimongo/Model.qll deleted file mode 100644 index 56b1470166b..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/minimongo/Model.qll +++ /dev/null @@ -1,86 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "minimongo.HybridCollection;minimongo.HybridCollectionStatic;Instance", // - "minimongo.HybridCollection;minimongo/lib/HybridDb.HybridCollection;", // - "minimongo.HybridCollection;minimongo/lib/HybridDb.default;Member[collections].AnyMember", // - "minimongo.HybridCollectionStatic;minimongo/lib/HybridDb.HybridCollectionStatic;", // - "minimongo.HybridCollectionStatic;minimongo/lib/HybridDb;Member[HybridCollection]", // - "minimongo.HybridCollectionStatic;minimongo;Member[HybridCollection]", // - "minimongo.MinimongoBaseCollection;minimongo.HybridCollection;", // - "minimongo.MinimongoBaseCollection;minimongo.MinimongoCollection;", // - "minimongo.MinimongoBaseCollection;minimongo.MinimongoDb;AnyMember", // - "minimongo.MinimongoBaseCollection;minimongo.MinimongoLocalCollection;", // - "minimongo.MinimongoBaseCollection;minimongo/RemoteDb.Collection;", // - "minimongo.MinimongoBaseCollection;minimongo/lib/types.MinimongoBaseCollection;", // - "minimongo.MinimongoCollection;minimongo.HybridCollection;Member[remoteCol]", // - "minimongo.MinimongoCollection;minimongo.MinimongoDb;Member[collections].AnyMember", // - "minimongo.MinimongoCollection;minimongo/lib/LocalStorageDb.default;Member[collections].AnyMember", // - "minimongo.MinimongoCollection;minimongo/lib/WebSQLDb.default;Member[collections].AnyMember", // - "minimongo.MinimongoCollection;minimongo/lib/types.MinimongoCollection;", // - "minimongo.MinimongoDb;minimongo.MinimongoDb;Member[remoteDb]", // - "minimongo.MinimongoDb;minimongo.MinimongoLocalDb;", // - "minimongo.MinimongoDb;minimongo/lib/HybridDb.default;", // - "minimongo.MinimongoDb;minimongo/lib/HybridDb.default;Member[remoteDb]", // - "minimongo.MinimongoDb;minimongo/lib/LocalStorageDb.default;", // - "minimongo.MinimongoDb;minimongo/lib/MemoryDb.default;", // - "minimongo.MinimongoDb;minimongo/lib/RemoteDb.default;", // - "minimongo.MinimongoDb;minimongo/lib/ReplicatingDb.default;Member[masterDb,replicaDb]", // - "minimongo.MinimongoDb;minimongo/lib/WebSQLDb.default;", // - "minimongo.MinimongoDb;minimongo/lib/types.MinimongoDb;", // - "minimongo.MinimongoLocalCollection;minimongo.HybridCollection;Member[localCol]", // - "minimongo.MinimongoLocalCollection;minimongo.MinimongoCollection;", // - "minimongo.MinimongoLocalCollection;minimongo.MinimongoLocalDb;Member[addCollection].Argument[2].Argument[0]", // - "minimongo.MinimongoLocalCollection;minimongo.MinimongoLocalDb;Member[collections].AnyMember", // - "minimongo.MinimongoLocalCollection;minimongo/IndexedDb.IndexedDbCollection;", // - "minimongo.MinimongoLocalCollection;minimongo/MemoryDb.Collection;", // - "minimongo.MinimongoLocalCollection;minimongo/ReplicatingDb.Collection;", // - "minimongo.MinimongoLocalCollection;minimongo/ReplicatingDb.Collection;Member[masterCol,replicaCol]", // - "minimongo.MinimongoLocalCollection;minimongo/lib/types.MinimongoLocalCollection;", // - "minimongo.MinimongoLocalDb;minimongo.MinimongoDb;Member[localDb]", // - "minimongo.MinimongoLocalDb;minimongo/lib/HybridDb.default;Member[localDb]", // - "minimongo.MinimongoLocalDb;minimongo/lib/IndexedDb.default;", // - "minimongo.MinimongoLocalDb;minimongo/lib/ReplicatingDb.default;", // - "minimongo.MinimongoLocalDb;minimongo/lib/types.MinimongoLocalDb;", // - "minimongo/IndexedDb.IndexedDbCollection;minimongo/IndexedDb.IndexedDbCollectionStatic;Instance", // - "minimongo/IndexedDb.IndexedDbCollection;minimongo/lib/IndexedDb.default;Member[collections].AnyMember", // - "minimongo/MemoryDb.Collection;minimongo/MemoryDb.CollectionStatic;Instance", // - "minimongo/MemoryDb.Collection;minimongo/lib/MemoryDb.default;Member[collections].AnyMember", // - "minimongo/RemoteDb.Collection;minimongo/RemoteDb.CollectionStatic;Instance", // - "minimongo/RemoteDb.Collection;minimongo/lib/RemoteDb.default;Member[collections].AnyMember", // - "minimongo/ReplicatingDb.Collection;minimongo/ReplicatingDb.CollectionStatic;Instance", // - "minimongo/ReplicatingDb.Collection;minimongo/lib/ReplicatingDb.default;Member[collections].AnyMember", // - "minimongo/lib/HybridDb.default;minimongo/lib/HybridDb.defaultStatic;Instance", // - "minimongo/lib/HybridDb.defaultStatic;minimongo/lib/HybridDb;Member[default]", // - "minimongo/lib/HybridDb.defaultStatic;minimongo;Member[HybridDb]", // - "minimongo/lib/IndexedDb.default;minimongo/lib/IndexedDb.defaultStatic;Instance", // - "minimongo/lib/IndexedDb.default;minimongo;Member[utils].Member[autoselectLocalDb].ReturnValue", // - "minimongo/lib/IndexedDb.defaultStatic;minimongo/lib/IndexedDb;Member[default]", // - "minimongo/lib/IndexedDb.defaultStatic;minimongo;Member[IndexedDb]", // - "minimongo/lib/LocalStorageDb.default;minimongo/lib/LocalStorageDb.defaultStatic;Instance", // - "minimongo/lib/LocalStorageDb.default;minimongo;Member[utils].Member[autoselectLocalDb].ReturnValue", // - "minimongo/lib/LocalStorageDb.defaultStatic;minimongo/lib/LocalStorageDb;Member[default]", // - "minimongo/lib/LocalStorageDb.defaultStatic;minimongo;Member[LocalStorageDb]", // - "minimongo/lib/MemoryDb.default;minimongo/lib/MemoryDb.defaultStatic;Instance", // - "minimongo/lib/MemoryDb.default;minimongo;Member[utils].Member[autoselectLocalDb].ReturnValue", // - "minimongo/lib/MemoryDb.defaultStatic;minimongo/lib/MemoryDb;Member[default]", // - "minimongo/lib/MemoryDb.defaultStatic;minimongo;Member[MemoryDb]", // - "minimongo/lib/RemoteDb.default;minimongo/lib/RemoteDb.defaultStatic;Instance", // - "minimongo/lib/RemoteDb.defaultStatic;minimongo/lib/RemoteDb;Member[default]", // - "minimongo/lib/RemoteDb.defaultStatic;minimongo;Member[RemoteDb]", // - "minimongo/lib/ReplicatingDb.default;minimongo/lib/ReplicatingDb.defaultStatic;Instance", // - "minimongo/lib/ReplicatingDb.defaultStatic;minimongo/lib/ReplicatingDb;Member[default]", // - "minimongo/lib/ReplicatingDb.defaultStatic;minimongo;Member[ReplicatingDb]", // - "minimongo/lib/WebSQLDb.default;minimongo/lib/WebSQLDb.defaultStatic;Instance", // - "minimongo/lib/WebSQLDb.default;minimongo;Member[utils].Member[autoselectLocalDb].ReturnValue", // - "minimongo/lib/WebSQLDb.defaultStatic;minimongo/lib/WebSQLDb;Member[default]", // - "minimongo/lib/WebSQLDb.defaultStatic;minimongo;Member[WebSQLDb]", // - "mongodb.Collection;minimongo.MinimongoBaseCollection;", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/minimongo/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/minimongo/model.yml new file mode 100644 index 00000000000..0c0d443fc3f --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/minimongo/model.yml @@ -0,0 +1,80 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [minimongo.HybridCollection, minimongo.HybridCollectionStatic, Instance] + - [minimongo.HybridCollection, "minimongo/lib/HybridDb.HybridCollection", ""] + - [minimongo.HybridCollection, "minimongo/lib/HybridDb.default", "Member[collections].AnyMember"] + - [minimongo.HybridCollectionStatic, "minimongo/lib/HybridDb.HybridCollectionStatic", ""] + - [minimongo.HybridCollectionStatic, "minimongo/lib/HybridDb", "Member[HybridCollection]"] + - [minimongo.HybridCollectionStatic, minimongo, "Member[HybridCollection]"] + - [minimongo.MinimongoBaseCollection, minimongo.HybridCollection, ""] + - [minimongo.MinimongoBaseCollection, minimongo.MinimongoCollection, ""] + - [minimongo.MinimongoBaseCollection, minimongo.MinimongoDb, AnyMember] + - [minimongo.MinimongoBaseCollection, minimongo.MinimongoLocalCollection, ""] + - [minimongo.MinimongoBaseCollection, "minimongo/RemoteDb.Collection", ""] + - [minimongo.MinimongoBaseCollection, "minimongo/lib/types.MinimongoBaseCollection", ""] + - [minimongo.MinimongoCollection, minimongo.HybridCollection, "Member[remoteCol]"] + - [minimongo.MinimongoCollection, minimongo.MinimongoDb, "Member[collections].AnyMember"] + - [minimongo.MinimongoCollection, "minimongo/lib/LocalStorageDb.default", "Member[collections].AnyMember"] + - [minimongo.MinimongoCollection, "minimongo/lib/WebSQLDb.default", "Member[collections].AnyMember"] + - [minimongo.MinimongoCollection, "minimongo/lib/types.MinimongoCollection", ""] + - [minimongo.MinimongoDb, minimongo.MinimongoDb, "Member[remoteDb]"] + - [minimongo.MinimongoDb, minimongo.MinimongoLocalDb, ""] + - [minimongo.MinimongoDb, "minimongo/lib/HybridDb.default", ""] + - [minimongo.MinimongoDb, "minimongo/lib/HybridDb.default", "Member[remoteDb]"] + - [minimongo.MinimongoDb, "minimongo/lib/LocalStorageDb.default", ""] + - [minimongo.MinimongoDb, "minimongo/lib/MemoryDb.default", ""] + - [minimongo.MinimongoDb, "minimongo/lib/RemoteDb.default", ""] + - [minimongo.MinimongoDb, "minimongo/lib/ReplicatingDb.default", "Member[masterDb,replicaDb]"] + - [minimongo.MinimongoDb, "minimongo/lib/WebSQLDb.default", ""] + - [minimongo.MinimongoDb, "minimongo/lib/types.MinimongoDb", ""] + - [minimongo.MinimongoLocalCollection, minimongo.HybridCollection, "Member[localCol]"] + - [minimongo.MinimongoLocalCollection, minimongo.MinimongoCollection, ""] + - [minimongo.MinimongoLocalCollection, minimongo.MinimongoLocalDb, "Member[addCollection].Argument[2].Argument[0]"] + - [minimongo.MinimongoLocalCollection, minimongo.MinimongoLocalDb, "Member[collections].AnyMember"] + - [minimongo.MinimongoLocalCollection, "minimongo/IndexedDb.IndexedDbCollection", ""] + - [minimongo.MinimongoLocalCollection, "minimongo/MemoryDb.Collection", ""] + - [minimongo.MinimongoLocalCollection, "minimongo/ReplicatingDb.Collection", ""] + - [minimongo.MinimongoLocalCollection, "minimongo/ReplicatingDb.Collection", "Member[masterCol,replicaCol]"] + - [minimongo.MinimongoLocalCollection, "minimongo/lib/types.MinimongoLocalCollection", ""] + - [minimongo.MinimongoLocalDb, minimongo.MinimongoDb, "Member[localDb]"] + - [minimongo.MinimongoLocalDb, "minimongo/lib/HybridDb.default", "Member[localDb]"] + - [minimongo.MinimongoLocalDb, "minimongo/lib/IndexedDb.default", ""] + - [minimongo.MinimongoLocalDb, "minimongo/lib/ReplicatingDb.default", ""] + - [minimongo.MinimongoLocalDb, "minimongo/lib/types.MinimongoLocalDb", ""] + - ["minimongo/IndexedDb.IndexedDbCollection", "minimongo/IndexedDb.IndexedDbCollectionStatic", Instance] + - ["minimongo/IndexedDb.IndexedDbCollection", "minimongo/lib/IndexedDb.default", "Member[collections].AnyMember"] + - ["minimongo/MemoryDb.Collection", "minimongo/MemoryDb.CollectionStatic", Instance] + - ["minimongo/MemoryDb.Collection", "minimongo/lib/MemoryDb.default", "Member[collections].AnyMember"] + - ["minimongo/RemoteDb.Collection", "minimongo/RemoteDb.CollectionStatic", Instance] + - ["minimongo/RemoteDb.Collection", "minimongo/lib/RemoteDb.default", "Member[collections].AnyMember"] + - ["minimongo/ReplicatingDb.Collection", "minimongo/ReplicatingDb.CollectionStatic", Instance] + - ["minimongo/ReplicatingDb.Collection", "minimongo/lib/ReplicatingDb.default", "Member[collections].AnyMember"] + - ["minimongo/lib/HybridDb.default", "minimongo/lib/HybridDb.defaultStatic", Instance] + - ["minimongo/lib/HybridDb.defaultStatic", "minimongo/lib/HybridDb", "Member[default]"] + - ["minimongo/lib/HybridDb.defaultStatic", minimongo, "Member[HybridDb]"] + - ["minimongo/lib/IndexedDb.default", "minimongo/lib/IndexedDb.defaultStatic", Instance] + - ["minimongo/lib/IndexedDb.default", minimongo, "Member[utils].Member[autoselectLocalDb].ReturnValue"] + - ["minimongo/lib/IndexedDb.defaultStatic", "minimongo/lib/IndexedDb", "Member[default]"] + - ["minimongo/lib/IndexedDb.defaultStatic", minimongo, "Member[IndexedDb]"] + - ["minimongo/lib/LocalStorageDb.default", "minimongo/lib/LocalStorageDb.defaultStatic", Instance] + - ["minimongo/lib/LocalStorageDb.default", minimongo, "Member[utils].Member[autoselectLocalDb].ReturnValue"] + - ["minimongo/lib/LocalStorageDb.defaultStatic", "minimongo/lib/LocalStorageDb", "Member[default]"] + - ["minimongo/lib/LocalStorageDb.defaultStatic", minimongo, "Member[LocalStorageDb]"] + - ["minimongo/lib/MemoryDb.default", "minimongo/lib/MemoryDb.defaultStatic", Instance] + - ["minimongo/lib/MemoryDb.default", minimongo, "Member[utils].Member[autoselectLocalDb].ReturnValue"] + - ["minimongo/lib/MemoryDb.defaultStatic", "minimongo/lib/MemoryDb", "Member[default]"] + - ["minimongo/lib/MemoryDb.defaultStatic", minimongo, "Member[MemoryDb]"] + - ["minimongo/lib/RemoteDb.default", "minimongo/lib/RemoteDb.defaultStatic", Instance] + - ["minimongo/lib/RemoteDb.defaultStatic", "minimongo/lib/RemoteDb", "Member[default]"] + - ["minimongo/lib/RemoteDb.defaultStatic", minimongo, "Member[RemoteDb]"] + - ["minimongo/lib/ReplicatingDb.default", "minimongo/lib/ReplicatingDb.defaultStatic", Instance] + - ["minimongo/lib/ReplicatingDb.defaultStatic", "minimongo/lib/ReplicatingDb", "Member[default]"] + - ["minimongo/lib/ReplicatingDb.defaultStatic", minimongo, "Member[ReplicatingDb]"] + - ["minimongo/lib/WebSQLDb.default", "minimongo/lib/WebSQLDb.defaultStatic", Instance] + - ["minimongo/lib/WebSQLDb.default", minimongo, "Member[utils].Member[autoselectLocalDb].ReturnValue"] + - ["minimongo/lib/WebSQLDb.defaultStatic", "minimongo/lib/WebSQLDb", "Member[default]"] + - ["minimongo/lib/WebSQLDb.defaultStatic", minimongo, "Member[WebSQLDb]"] + - [mongodb.Collection, minimongo.MinimongoBaseCollection, ""] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mongodb/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/mongodb/Model.qll deleted file mode 100644 index 4cceff77185..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/mongodb/Model.qll +++ /dev/null @@ -1,806 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Sinks extends ModelInput::SinkModelCsv { - override predicate row(string row) { - row = - [ - "mongodb.Collection;Member[aggregate,count,countDocuments,deleteMany,deleteOne,find,findOne,findOneAndDelete,findOneAndReplace,remove,replaceOne,watch].Argument[0];mongodb.sink", // - "mongodb.Collection;Member[distinct].Argument[1];mongodb.sink", // - "mongodb.Collection;Member[findOneAndUpdate,update,updateMany,updateOne].Argument[0,1];mongodb.sink", // - "mongodb.Db;Member[aggregate,watch].Argument[0];mongodb.sink", // - "mongodb.DeleteManyModel;Member[filter];mongodb.sink", // - "mongodb.DeleteOneModel;Member[filter];mongodb.sink", // - "mongodb.MongoClient;Member[watch].Argument[0];mongodb.sink", // - "mongodb.UpdateManyModel;Member[filter,update];mongodb.sink", // - "mongodb.UpdateOneModel;Member[filter,update];mongodb.sink", // - "mongoose.CollectionBase;Member[findAndModify].Argument[0];mongodb.sink", // - "mongoose.Connection;Member[watch].Argument[0];mongodb.sink", // - "mongoose.Document;Member[update,updateOne].Argument[0];mongodb.sink", // - "mongoose.Model;Member[$where,aggregate,exists,find,findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove,findOneAndReplace,geoSearch,remove,replaceOne,watch].Argument[0];mongodb.sink", // - "mongoose.Model;Member[count,where].WithArity[1,2].Argument[0];mongodb.sink", // - "mongoose.Model;Member[countDocuments].WithArity[1,2,3].Argument[0];mongodb.sink", // - "mongoose.Model;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0];mongodb.sink", // - "mongoose.Model;Member[distinct,where].Argument[1];mongodb.sink", // - "mongoose.Model;Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[0,1];mongodb.sink", // - "mongoose.Model;Member[find].WithArity[1,2,3,4].Argument[0];mongodb.sink", // - "mongoose.Query;Member[$where,and,find,findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove,nor,or,remove,replaceOne,setUpdate].Argument[0];mongodb.sink", // - "mongoose.Query;Member[count,where].WithArity[1,2].Argument[0];mongodb.sink", // - "mongoose.Query;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0];mongodb.sink", // - "mongoose.Query;Member[distinct,where].Argument[1];mongodb.sink", // - "mongoose.Query;Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[0,1];mongodb.sink", // - "mongoose.Query;Member[find].WithArity[1,2,3,4].Argument[0];mongodb.sink", // - "mongoose.QueryStatic;Argument[2];mongodb.sink", // - ] - } -} - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "mongodb.AbstractCursor;mongodb.FindCursor;", // - "mongodb.AbstractCursor;mongodb.ListCollectionsCursor;", // - "mongodb.AbstractCursor;mongodb.ListIndexesCursor;", // - "mongodb.AbstractCursorOptions;mongodb.AggregationCursorOptions;", // - "mongodb.AbstractCursorOptions;mongodb/mongodb.AbstractCursorOptions;", // - "mongodb.AbstractCursorOptions;mongoose.mongodb.AbstractCursorOptions;", // - "mongodb.AddUserOptions;mongodb.Admin;Member[addUser].Argument[1,2]", // - "mongodb.AddUserOptions;mongodb.Db;Member[addUser].Argument[1,2]", // - "mongodb.AddUserOptions;mongodb/mongodb.AddUserOptions;", // - "mongodb.AddUserOptions;mongoose.mongodb.AddUserOptions;", // - "mongodb.Admin;mongodb.AdminStatic;Instance", // - "mongodb.Admin;mongodb.Db;Member[admin].ReturnValue", // - "mongodb.Admin;mongodb/mongodb.Admin;", // - "mongodb.Admin;mongoose.mongodb.Admin;", // - "mongodb.AdminStatic;mongodb/mongodb.AdminStatic;", // - "mongodb.AdminStatic;mongodb;Member[Admin]", // - "mongodb.AdminStatic;mongoose.mongodb.AdminStatic;", // - "mongodb.AggregateOptions;mongodb.AggregationCursorOptions;", // - "mongodb.AggregateOptions;mongodb.ChangeStreamOptions;", // - "mongodb.AggregateOptions;mongodb.Collection;Member[aggregate].Argument[1]", // - "mongodb.AggregateOptions;mongodb.CountDocumentsOptions;", // - "mongodb.AggregateOptions;mongodb.Db;Member[aggregate].Argument[1]", // - "mongodb.AggregateOptions;mongodb/mongodb.AggregateOptions;", // - "mongodb.AggregateOptions;mongoose.mongodb.AggregateOptions;", // - "mongodb.AggregationCursorOptions;mongodb/mongodb.AggregationCursorOptions;", // - "mongodb.AggregationCursorOptions;mongoose.mongodb.AggregationCursorOptions;", // - "mongodb.AnyBulkWriteOperation;mongodb.BulkOperationBase;Member[raw].Argument[0]", // - "mongodb.AnyBulkWriteOperation;mongodb.Collection;Member[bulkWrite].Argument[0].ArrayElement", // - "mongodb.AnyBulkWriteOperation;mongodb/mongodb.AnyBulkWriteOperation;", // - "mongodb.AnyBulkWriteOperation;mongoose.mongodb.AnyBulkWriteOperation;", // - "mongodb.Auth;mongodb.MongoClientOptions;Member[auth]", // - "mongodb.Auth;mongodb/mongodb.Auth;", // - "mongodb.Auth;mongoose.mongodb.Auth;", // - "mongodb.AutoEncrypter;mongodb.AutoEncrypter;Instance", // - "mongodb.AutoEncrypter;mongodb.ConnectionOptions;Member[autoEncrypter]", // - "mongodb.AutoEncrypter;mongodb.MongoClient;Member[autoEncrypter]", // - "mongodb.AutoEncrypter;mongodb.MongoOptions;Member[autoEncrypter]", // - "mongodb.AutoEncrypter;mongodb/mongodb.AutoEncrypter;", // - "mongodb.AutoEncrypter;mongoose.mongodb.AutoEncrypter;", // - "mongodb.AutoEncryptionOptions;mongodb.AutoEncrypter;Argument[1]", // - "mongodb.AutoEncryptionOptions;mongodb.MongoClientOptions;Member[autoEncryption]", // - "mongodb.AutoEncryptionOptions;mongodb/mongodb.AutoEncryptionOptions;", // - "mongodb.AutoEncryptionOptions;mongoose.mongodb.AutoEncryptionOptions;", // - "mongodb.BulkOperationBase;mongodb.BulkOperationBase;Member[addToOperationsList,insert,raw].ReturnValue", // - "mongodb.BulkOperationBase;mongodb.BulkOperationBaseStatic;Instance", // - "mongodb.BulkOperationBase;mongodb.FindOperators;Member[bulkOperation]", // - "mongodb.BulkOperationBase;mongodb.FindOperators;Member[delete,deleteOne,replaceOne,update,updateOne].ReturnValue", // - "mongodb.BulkOperationBase;mongodb.OrderedBulkOperation;", // - "mongodb.BulkOperationBase;mongodb.UnorderedBulkOperation;", // - "mongodb.BulkOperationBase;mongodb/mongodb.BulkOperationBase;", // - "mongodb.BulkOperationBase;mongoose.mongodb.BulkOperationBase;", // - "mongodb.BulkOperationBaseStatic;mongodb/mongodb.BulkOperationBaseStatic;", // - "mongodb.BulkOperationBaseStatic;mongodb;Member[BulkOperationBase]", // - "mongodb.BulkOperationBaseStatic;mongoose.mongodb.BulkOperationBaseStatic;", // - "mongodb.BulkWriteOptions;mongodb.BulkOperationBase;Member[execute].WithArity[0,1,2].Argument[0]", // - "mongodb.BulkWriteOptions;mongodb.Collection;Member[bulkWrite,insert,insertMany].Argument[1]", // - "mongodb.BulkWriteOptions;mongodb.Collection;Member[initializeOrderedBulkOp,initializeUnorderedBulkOp].Argument[0]", // - "mongodb.BulkWriteOptions;mongodb.OrderedBulkOperationStatic;Argument[1]", // - "mongodb.BulkWriteOptions;mongodb.UnorderedBulkOperationStatic;Argument[1]", // - "mongodb.BulkWriteOptions;mongodb/mongodb.BulkWriteOptions;", // - "mongodb.BulkWriteOptions;mongoose.mongodb.BulkWriteOptions;", // - "mongodb.ChangeStream;mongodb.ChangeStreamStatic;Instance", // - "mongodb.ChangeStream;mongodb.Collection;Member[watch].ReturnValue", // - "mongodb.ChangeStream;mongodb.Db;Member[watch].ReturnValue", // - "mongodb.ChangeStream;mongodb.MongoClient;Member[watch].ReturnValue", // - "mongodb.ChangeStream;mongodb/mongodb.ChangeStream;", // - "mongodb.ChangeStream;mongoose.mongodb.ChangeStream;", // - "mongodb.ChangeStreamOptions;mongodb.ChangeStream;Member[options]", // - "mongodb.ChangeStreamOptions;mongodb.Collection;Member[watch].Argument[1]", // - "mongodb.ChangeStreamOptions;mongodb.Db;Member[watch].Argument[1]", // - "mongodb.ChangeStreamOptions;mongodb.MongoClient;Member[watch].Argument[1]", // - "mongodb.ChangeStreamOptions;mongodb/mongodb.ChangeStreamOptions;", // - "mongodb.ChangeStreamOptions;mongoose.mongodb.ChangeStreamOptions;", // - "mongodb.ChangeStreamStatic;mongodb/mongodb.ChangeStreamStatic;", // - "mongodb.ChangeStreamStatic;mongodb;Member[ChangeStream]", // - "mongodb.ChangeStreamStatic;mongoose.mongodb.ChangeStreamStatic;", // - "mongodb.ClientSession;mongodb.AbstractCursorOptions;Member[session]", // - "mongodb.ClientSession;mongodb.ClientSession;Member[equals].Argument[0]", // - "mongodb.ClientSession;mongodb.ClientSessionEvents;Member[ended].Argument[0]", // - "mongodb.ClientSession;mongodb.ClientSessionStatic;Instance", // - "mongodb.ClientSession;mongodb.IndexInformationOptions;Member[session]", // - "mongodb.ClientSession;mongodb.MongoClient;Member[startSession].ReturnValue", // - "mongodb.ClientSession;mongodb.OperationOptions;Member[session]", // - "mongodb.ClientSession;mongodb.ReadPreferenceFromOptions;Member[session]", // - "mongodb.ClientSession;mongodb.SelectServerOptions;Member[session]", // - "mongodb.ClientSession;mongodb.WithSessionCallback;Argument[0]", // - "mongodb.ClientSession;mongodb.WithTransactionCallback;Argument[0]", // - "mongodb.ClientSession;mongodb/mongodb.ClientSession;", // - "mongodb.ClientSession;mongoose.mongodb.ClientSession;", // - "mongodb.ClientSessionEvents;mongodb/mongodb.ClientSessionEvents;", // - "mongodb.ClientSessionEvents;mongoose.mongodb.ClientSessionEvents;", // - "mongodb.ClientSessionOptions;mongodb.MongoClient;Member[startSession].Argument[0]", // - "mongodb.ClientSessionOptions;mongodb.MongoClient;Member[withSession].WithArity[2].Argument[0]", // - "mongodb.ClientSessionOptions;mongodb/mongodb.ClientSessionOptions;", // - "mongodb.ClientSessionOptions;mongoose.mongodb.ClientSessionOptions;", // - "mongodb.ClientSessionStatic;mongodb/mongodb.ClientSessionStatic;", // - "mongodb.ClientSessionStatic;mongodb;Member[ClientSession]", // - "mongodb.ClientSessionStatic;mongoose.mongodb.ClientSessionStatic;", // - "mongodb.CollStatsOptions;mongodb.Collection;Member[stats].Argument[0]", // - "mongodb.CollStatsOptions;mongodb/mongodb.CollStatsOptions;", // - "mongodb.CollStatsOptions;mongoose.mongodb.CollStatsOptions;", // - "mongodb.Collection;mongodb.ChangeStream;Member[parent]", // - "mongodb.Collection;mongodb.Collection;Member[rename].Argument[1,2].TypeVar[mongodb.Callback.0]", // - "mongodb.Collection;mongodb.Collection;Member[rename].WithArity[1,2].ReturnValue.Awaited", // - "mongodb.Collection;mongodb.CollectionStatic;Instance", // - "mongodb.Collection;mongodb.Db;Member[collection].ReturnValue", // - "mongodb.Collection;mongodb.Db;Member[collections].Argument[0,1].TypeVar[mongodb.Callback.0].ArrayElement", // - "mongodb.Collection;mongodb.Db;Member[collections].WithArity[0,1].ReturnValue.Awaited.ArrayElement", // - "mongodb.Collection;mongodb.Db;Member[createCollection].Argument[2].TypeVar[mongodb.Callback.0]", // - "mongodb.Collection;mongodb.Db;Member[createCollection].WithArity[1,2].ReturnValue.Awaited", // - "mongodb.Collection;mongodb.Db;Member[createCollection].WithArity[2].Argument[1].TypeVar[mongodb.Callback.0]", // - "mongodb.Collection;mongodb.Db;Member[renameCollection].Argument[2,3].TypeVar[mongodb.Callback.0]", // - "mongodb.Collection;mongodb.Db;Member[renameCollection].WithArity[2,3].ReturnValue.Awaited", // - "mongodb.Collection;mongodb.GridFSBucketWriteStream;Member[chunks,files]", // - "mongodb.Collection;mongodb.ListIndexesCursor;Member[parent]", // - "mongodb.Collection;mongodb.ListIndexesCursorStatic;Argument[0]", // - "mongodb.Collection;mongodb.OrderedBulkOperationStatic;Argument[0]", // - "mongodb.Collection;mongodb.UnorderedBulkOperationStatic;Argument[0]", // - "mongodb.Collection;mongodb/mongodb.Collection;", // - "mongodb.Collection;mongoose.mongodb.Collection;", // - "mongodb.CollectionStatic;mongodb/mongodb.CollectionStatic;", // - "mongodb.CollectionStatic;mongodb;Member[Collection]", // - "mongodb.CollectionStatic;mongoose.mongodb.CollectionStatic;", // - "mongodb.CommandOperationOptions;mongodb.AddUserOptions;", // - "mongodb.CommandOperationOptions;mongodb.Admin;Member[buildInfo,ping,replSetGetStatus,serverInfo,serverStatus].Argument[0]", // - "mongodb.CommandOperationOptions;mongodb.AggregateOptions;", // - "mongodb.CommandOperationOptions;mongodb.BulkWriteOptions;", // - "mongodb.CommandOperationOptions;mongodb.CollStatsOptions;", // - "mongodb.CommandOperationOptions;mongodb.CountOptions;", // - "mongodb.CommandOperationOptions;mongodb.CreateCollectionOptions;", // - "mongodb.CommandOperationOptions;mongodb.CreateIndexesOptions;", // - "mongodb.CommandOperationOptions;mongodb.DbStatsOptions;", // - "mongodb.CommandOperationOptions;mongodb.DeleteOptions;", // - "mongodb.CommandOperationOptions;mongodb.DistinctOptions;", // - "mongodb.CommandOperationOptions;mongodb.DropCollectionOptions;", // - "mongodb.CommandOperationOptions;mongodb.DropDatabaseOptions;", // - "mongodb.CommandOperationOptions;mongodb.DropIndexesOptions;", // - "mongodb.CommandOperationOptions;mongodb.EstimatedDocumentCountOptions;", // - "mongodb.CommandOperationOptions;mongodb.EvalOptions;", // - "mongodb.CommandOperationOptions;mongodb.FindOneAndDeleteOptions;", // - "mongodb.CommandOperationOptions;mongodb.FindOneAndReplaceOptions;", // - "mongodb.CommandOperationOptions;mongodb.FindOneAndUpdateOptions;", // - "mongodb.CommandOperationOptions;mongodb.FindOptions;", // - "mongodb.CommandOperationOptions;mongodb.InsertOneOptions;", // - "mongodb.CommandOperationOptions;mongodb.ListCollectionsOptions;", // - "mongodb.CommandOperationOptions;mongodb.ListDatabasesOptions;", // - "mongodb.CommandOperationOptions;mongodb.ListIndexesOptions;", // - "mongodb.CommandOperationOptions;mongodb.MapReduceOptions;", // - "mongodb.CommandOperationOptions;mongodb.ProfilingLevelOptions;", // - "mongodb.CommandOperationOptions;mongodb.RemoveUserOptions;", // - "mongodb.CommandOperationOptions;mongodb.RenameOptions;", // - "mongodb.CommandOperationOptions;mongodb.ReplaceOptions;", // - "mongodb.CommandOperationOptions;mongodb.RunCommandOptions;", // - "mongodb.CommandOperationOptions;mongodb.SetProfilingLevelOptions;", // - "mongodb.CommandOperationOptions;mongodb.TransactionOptions;", // - "mongodb.CommandOperationOptions;mongodb.UpdateOptions;", // - "mongodb.CommandOperationOptions;mongodb.ValidateCollectionOptions;", // - "mongodb.CommandOperationOptions;mongodb/mongodb.CommandOperationOptions;", // - "mongodb.CommandOperationOptions;mongoose.mongodb.CommandOperationOptions;", // - "mongodb.ConnectionOptions;mongodb/mongodb.ConnectionOptions;", // - "mongodb.ConnectionOptions;mongoose.mongodb.ConnectionOptions;", // - "mongodb.CountDocumentsOptions;mongodb.Collection;Member[countDocuments].Argument[1]", // - "mongodb.CountDocumentsOptions;mongodb/mongodb.CountDocumentsOptions;", // - "mongodb.CountDocumentsOptions;mongoose.mongodb.CountDocumentsOptions;", // - "mongodb.CountOptions;mongodb.Collection;Member[count].Argument[1]", // - "mongodb.CountOptions;mongodb.FindCursor;Member[count].Argument[0]", // - "mongodb.CountOptions;mongodb/mongodb.CountOptions;", // - "mongodb.CountOptions;mongoose.mongodb.CountOptions;", // - "mongodb.CreateCollectionOptions;mongodb.Db;Member[createCollection].WithArity[1,2,3].Argument[1]", // - "mongodb.CreateCollectionOptions;mongodb/mongodb.CreateCollectionOptions;", // - "mongodb.CreateCollectionOptions;mongoose.mongodb.CreateCollectionOptions;", // - "mongodb.CreateIndexesOptions;mongodb.Collection;Member[createIndex,createIndexes].Argument[1]", // - "mongodb.CreateIndexesOptions;mongodb.Db;Member[createIndex].Argument[2]", // - "mongodb.CreateIndexesOptions;mongodb/mongodb.CreateIndexesOptions;", // - "mongodb.CreateIndexesOptions;mongoose.mongodb.CreateIndexesOptions;", // - "mongodb.Db;mongodb.ChangeStream;Member[parent]", // - "mongodb.Db;mongodb.DbStatic;Instance", // - "mongodb.Db;mongodb.GridFSBucketStatic;Argument[0]", // - "mongodb.Db;mongodb.ListCollectionsCursor;Member[parent]", // - "mongodb.Db;mongodb.ListCollectionsCursorStatic;Argument[0]", // - "mongodb.Db;mongodb.MongoClient;Member[db].ReturnValue", // - "mongodb.Db;mongodb/mongodb.Db;", // - "mongodb.Db;mongoose.mongodb.Db;", // - "mongodb.DbStatic;mongodb/mongodb.DbStatic;", // - "mongodb.DbStatic;mongodb;Member[Db]", // - "mongodb.DbStatic;mongoose.mongodb.DbStatic;", // - "mongodb.DbStatsOptions;mongodb.Db;Member[stats].Argument[0]", // - "mongodb.DbStatsOptions;mongodb/mongodb.DbStatsOptions;", // - "mongodb.DbStatsOptions;mongoose.mongodb.DbStatsOptions;", // - "mongodb.DeleteManyModel;mongodb.AnyBulkWriteOperation;Member[deleteMany]", // - "mongodb.DeleteManyModel;mongodb/mongodb.DeleteManyModel;", // - "mongodb.DeleteManyModel;mongoose.mongodb.DeleteManyModel;", // - "mongodb.DeleteOneModel;mongodb.AnyBulkWriteOperation;Member[deleteOne]", // - "mongodb.DeleteOneModel;mongodb/mongodb.DeleteOneModel;", // - "mongodb.DeleteOneModel;mongoose.mongodb.DeleteOneModel;", // - "mongodb.DeleteOptions;mongodb.Collection;Member[deleteMany,deleteOne,remove].Argument[1]", // - "mongodb.DeleteOptions;mongodb/mongodb.DeleteOptions;", // - "mongodb.DeleteOptions;mongoose.mongodb.DeleteOptions;", // - "mongodb.DistinctOptions;mongodb.Collection;Member[distinct].Argument[2]", // - "mongodb.DistinctOptions;mongodb/mongodb.DistinctOptions;", // - "mongodb.DistinctOptions;mongoose.mongodb.DistinctOptions;", // - "mongodb.DropCollectionOptions;mongodb.Collection;Member[drop].Argument[0]", // - "mongodb.DropCollectionOptions;mongodb.Db;Member[dropCollection].Argument[1]", // - "mongodb.DropCollectionOptions;mongodb/mongodb.DropCollectionOptions;", // - "mongodb.DropCollectionOptions;mongoose.mongodb.DropCollectionOptions;", // - "mongodb.DropDatabaseOptions;mongodb.Db;Member[dropDatabase].Argument[0]", // - "mongodb.DropDatabaseOptions;mongodb/mongodb.DropDatabaseOptions;", // - "mongodb.DropDatabaseOptions;mongoose.mongodb.DropDatabaseOptions;", // - "mongodb.DropIndexesOptions;mongodb.Collection;Member[dropIndex].Argument[1]", // - "mongodb.DropIndexesOptions;mongodb.Collection;Member[dropIndexes].Argument[0]", // - "mongodb.DropIndexesOptions;mongodb/mongodb.DropIndexesOptions;", // - "mongodb.DropIndexesOptions;mongoose.mongodb.DropIndexesOptions;", // - "mongodb.EstimatedDocumentCountOptions;mongodb.Collection;Member[estimatedDocumentCount].Argument[0]", // - "mongodb.EstimatedDocumentCountOptions;mongodb/mongodb.EstimatedDocumentCountOptions;", // - "mongodb.EstimatedDocumentCountOptions;mongoose.mongodb.EstimatedDocumentCountOptions;", // - "mongodb.EvalOptions;mongodb/mongodb.EvalOptions;", // - "mongodb.EvalOptions;mongoose.mongodb.EvalOptions;", // - "mongodb.FindCursor;mongodb.Collection;Member[find].WithArity[0,1,2].ReturnValue", // - "mongodb.FindCursor;mongodb.FindCursor;Member[addQueryModifier,allowDiskUse,clone,collation,comment,filter,hint,limit,map,max,maxAwaitTimeMS,maxTimeMS,min,project,returnKey,showRecordId,skip,sort].ReturnValue", // - "mongodb.FindCursor;mongodb.FindCursorStatic;Instance", // - "mongodb.FindCursor;mongodb.GridFSBucket;Member[find].ReturnValue", // - "mongodb.FindCursor;mongodb/mongodb.FindCursor;", // - "mongodb.FindCursor;mongoose.mongodb.FindCursor;", // - "mongodb.FindCursorStatic;mongodb/mongodb.FindCursorStatic;", // - "mongodb.FindCursorStatic;mongodb;Member[FindCursor]", // - "mongodb.FindCursorStatic;mongoose.mongodb.FindCursorStatic;", // - "mongodb.FindOneAndDeleteOptions;mongodb.Collection;Member[findOneAndDelete].Argument[1]", // - "mongodb.FindOneAndDeleteOptions;mongodb/mongodb.FindOneAndDeleteOptions;", // - "mongodb.FindOneAndDeleteOptions;mongoose.mongodb.FindOneAndDeleteOptions;", // - "mongodb.FindOneAndReplaceOptions;mongodb.Collection;Member[findOneAndReplace].Argument[2]", // - "mongodb.FindOneAndReplaceOptions;mongodb/mongodb.FindOneAndReplaceOptions;", // - "mongodb.FindOneAndReplaceOptions;mongoose.mongodb.FindOneAndReplaceOptions;", // - "mongodb.FindOneAndUpdateOptions;mongodb.Collection;Member[findOneAndUpdate].Argument[2]", // - "mongodb.FindOneAndUpdateOptions;mongodb/mongodb.FindOneAndUpdateOptions;", // - "mongodb.FindOneAndUpdateOptions;mongoose.mongodb.FindOneAndUpdateOptions;", // - "mongodb.FindOperators;mongodb.BulkOperationBase;Member[find].ReturnValue", // - "mongodb.FindOperators;mongodb.FindOperators;Member[arrayFilters,collation,upsert].ReturnValue", // - "mongodb.FindOperators;mongodb.FindOperatorsStatic;Instance", // - "mongodb.FindOperators;mongodb/mongodb.FindOperators;", // - "mongodb.FindOperators;mongoose.mongodb.FindOperators;", // - "mongodb.FindOperatorsStatic;mongodb/mongodb.FindOperatorsStatic;", // - "mongodb.FindOperatorsStatic;mongodb;Member[FindOperators]", // - "mongodb.FindOperatorsStatic;mongoose.mongodb.FindOperatorsStatic;", // - "mongodb.FindOptions;mongodb.Collection;Member[find,findOne].Argument[1]", // - "mongodb.FindOptions;mongodb.GridFSBucket;Member[find].Argument[1]", // - "mongodb.FindOptions;mongodb/mongodb.FindOptions;", // - "mongodb.FindOptions;mongoose.mongodb.FindOptions;", // - "mongodb.GridFSBucket;mongodb.GridFSBucketStatic;Instance", // - "mongodb.GridFSBucket;mongodb.GridFSBucketWriteStream;Member[bucket]", // - "mongodb.GridFSBucket;mongodb/mongodb.GridFSBucket;", // - "mongodb.GridFSBucket;mongoose.mongodb.GridFSBucket;", // - "mongodb.GridFSBucketStatic;mongodb/mongodb.GridFSBucketStatic;", // - "mongodb.GridFSBucketStatic;mongodb;Member[GridFSBucket]", // - "mongodb.GridFSBucketStatic;mongoose.mongodb.GridFSBucketStatic;", // - "mongodb.GridFSBucketWriteStream;mongodb.GridFSBucket;Member[openUploadStream,openUploadStreamWithId].ReturnValue", // - "mongodb.GridFSBucketWriteStream;mongodb.GridFSBucketWriteStream;Member[end].ReturnValue", // - "mongodb.GridFSBucketWriteStream;mongodb.GridFSBucketWriteStreamStatic;Instance", // - "mongodb.GridFSBucketWriteStream;mongodb/mongodb.GridFSBucketWriteStream;", // - "mongodb.GridFSBucketWriteStream;mongoose.mongodb.GridFSBucketWriteStream;", // - "mongodb.GridFSBucketWriteStreamStatic;mongodb/mongodb.GridFSBucketWriteStreamStatic;", // - "mongodb.GridFSBucketWriteStreamStatic;mongodb;Member[GridFSBucketWriteStream]", // - "mongodb.GridFSBucketWriteStreamStatic;mongoose.mongodb.GridFSBucketWriteStreamStatic;", // - "mongodb.IndexInformationOptions;mongodb.Collection;Member[indexExists].Argument[1]", // - "mongodb.IndexInformationOptions;mongodb.Collection;Member[indexInformation,indexes].Argument[0]", // - "mongodb.IndexInformationOptions;mongodb.Db;Member[indexInformation].Argument[1]", // - "mongodb.IndexInformationOptions;mongodb/mongodb.IndexInformationOptions;", // - "mongodb.IndexInformationOptions;mongoose.mongodb.IndexInformationOptions;", // - "mongodb.InsertOneOptions;mongodb.Collection;Member[insertOne].Argument[1]", // - "mongodb.InsertOneOptions;mongodb/mongodb.InsertOneOptions;", // - "mongodb.InsertOneOptions;mongoose.mongodb.InsertOneOptions;", // - "mongodb.ListCollectionsCursor;mongodb.Db;Member[listCollections].WithArity[0,1,2].ReturnValue", // - "mongodb.ListCollectionsCursor;mongodb.ListCollectionsCursor;Member[clone].ReturnValue", // - "mongodb.ListCollectionsCursor;mongodb.ListCollectionsCursorStatic;Instance", // - "mongodb.ListCollectionsCursor;mongodb/mongodb.ListCollectionsCursor;", // - "mongodb.ListCollectionsCursor;mongoose.mongodb.ListCollectionsCursor;", // - "mongodb.ListCollectionsCursorStatic;mongodb/mongodb.ListCollectionsCursorStatic;", // - "mongodb.ListCollectionsCursorStatic;mongodb;Member[ListCollectionsCursor]", // - "mongodb.ListCollectionsCursorStatic;mongoose.mongodb.ListCollectionsCursorStatic;", // - "mongodb.ListCollectionsOptions;mongodb.Db;Member[collections].Argument[0]", // - "mongodb.ListCollectionsOptions;mongodb.Db;Member[listCollections].WithArity[0,1,2].Argument[1]", // - "mongodb.ListCollectionsOptions;mongodb.ListCollectionsCursor;Member[options]", // - "mongodb.ListCollectionsOptions;mongodb.ListCollectionsCursorStatic;Argument[2]", // - "mongodb.ListCollectionsOptions;mongodb/mongodb.ListCollectionsOptions;", // - "mongodb.ListCollectionsOptions;mongoose.mongodb.ListCollectionsOptions;", // - "mongodb.ListDatabasesOptions;mongodb.Admin;Member[listDatabases].Argument[0]", // - "mongodb.ListDatabasesOptions;mongodb/mongodb.ListDatabasesOptions;", // - "mongodb.ListDatabasesOptions;mongoose.mongodb.ListDatabasesOptions;", // - "mongodb.ListIndexesCursor;mongodb.Collection;Member[listIndexes].ReturnValue", // - "mongodb.ListIndexesCursor;mongodb.ListIndexesCursor;Member[clone].ReturnValue", // - "mongodb.ListIndexesCursor;mongodb.ListIndexesCursorStatic;Instance", // - "mongodb.ListIndexesCursor;mongodb/mongodb.ListIndexesCursor;", // - "mongodb.ListIndexesCursor;mongoose.mongodb.ListIndexesCursor;", // - "mongodb.ListIndexesCursorStatic;mongodb/mongodb.ListIndexesCursorStatic;", // - "mongodb.ListIndexesCursorStatic;mongodb;Member[ListIndexesCursor]", // - "mongodb.ListIndexesCursorStatic;mongoose.mongodb.ListIndexesCursorStatic;", // - "mongodb.ListIndexesOptions;mongodb.Collection;Member[listIndexes].Argument[0]", // - "mongodb.ListIndexesOptions;mongodb.ListIndexesCursor;Member[options]", // - "mongodb.ListIndexesOptions;mongodb.ListIndexesCursorStatic;Argument[1]", // - "mongodb.ListIndexesOptions;mongodb/mongodb.ListIndexesOptions;", // - "mongodb.ListIndexesOptions;mongoose.mongodb.ListIndexesOptions;", // - "mongodb.MapReduceOptions;mongodb.Collection;Member[mapReduce].Argument[2]", // - "mongodb.MapReduceOptions;mongodb/mongodb.MapReduceOptions;", // - "mongodb.MapReduceOptions;mongoose.mongodb.MapReduceOptions;", // - "mongodb.MongoClient;mongodb.AutoEncrypter;Argument[0]", // - "mongodb.MongoClient;mongodb.AutoEncryptionOptions;Member[keyVaultClient]", // - "mongodb.MongoClient;mongodb.ChangeStream;Member[parent]", // - "mongodb.MongoClient;mongodb.DbStatic;Argument[0]", // - "mongodb.MongoClient;mongodb.MongoClient;Member[connect].Argument[0].TypeVar[mongodb.Callback.0]", // - "mongodb.MongoClient;mongodb.MongoClient;Member[connect].WithArity[0].ReturnValue.Awaited", // - "mongodb.MongoClient;mongodb.MongoClientEvents;Member[open].Argument[0]", // - "mongodb.MongoClient;mongodb.MongoClientStatic;Instance", // - "mongodb.MongoClient;mongodb.MongoClientStatic;Member[connect].Argument[1,2].TypeVar[mongodb.Callback.0]", // - "mongodb.MongoClient;mongodb.MongoClientStatic;Member[connect].WithArity[1,2].ReturnValue.Awaited", // - "mongodb.MongoClient;mongodb/mongodb.MongoClient;", // - "mongodb.MongoClient;mongoose.mongodb.MongoClient;", // - "mongodb.MongoClientEvents;mongodb/mongodb.MongoClientEvents;", // - "mongodb.MongoClientEvents;mongoose.mongodb.MongoClientEvents;", // - "mongodb.MongoClientOptions;mongodb.MongoClientStatic;Argument[1]", // - "mongodb.MongoClientOptions;mongodb.MongoClientStatic;Member[connect].Argument[1]", // - "mongodb.MongoClientOptions;mongodb/mongodb.MongoClientOptions;", // - "mongodb.MongoClientOptions;mongoose.mongodb.MongoClientOptions;", // - "mongodb.MongoClientStatic;mongodb/mongodb.MongoClientStatic;", // - "mongodb.MongoClientStatic;mongodb;Member[MongoClient]", // - "mongodb.MongoClientStatic;mongoose.mongodb.MongoClientStatic;", // - "mongodb.MongoOptions;mongodb.ClientSession;Member[clientOptions]", // - "mongodb.MongoOptions;mongodb.MongoClient;Member[options]", // - "mongodb.MongoOptions;mongodb/mongodb.MongoOptions;", // - "mongodb.MongoOptions;mongoose.mongodb.MongoOptions;", // - "mongodb.OperationOptions;mongodb.Collection;Member[isCapped,options].Argument[0]", // - "mongodb.OperationOptions;mongodb.CommandOperationOptions;", // - "mongodb.OperationOptions;mongodb/mongodb.OperationOptions;", // - "mongodb.OperationOptions;mongoose.mongodb.OperationOptions;", // - "mongodb.OrderedBulkOperation;mongodb.Collection;Member[initializeOrderedBulkOp].ReturnValue", // - "mongodb.OrderedBulkOperation;mongodb.OrderedBulkOperation;Member[addToOperationsList].ReturnValue", // - "mongodb.OrderedBulkOperation;mongodb.OrderedBulkOperationStatic;Instance", // - "mongodb.OrderedBulkOperation;mongodb/mongodb.OrderedBulkOperation;", // - "mongodb.OrderedBulkOperation;mongoose.mongodb.OrderedBulkOperation;", // - "mongodb.OrderedBulkOperationStatic;mongodb/mongodb.OrderedBulkOperationStatic;", // - "mongodb.OrderedBulkOperationStatic;mongodb;Member[OrderedBulkOperation]", // - "mongodb.OrderedBulkOperationStatic;mongoose.mongodb.OrderedBulkOperationStatic;", // - "mongodb.ProfilingLevelOptions;mongodb.Db;Member[profilingLevel].Argument[0]", // - "mongodb.ProfilingLevelOptions;mongodb/mongodb.ProfilingLevelOptions;", // - "mongodb.ProfilingLevelOptions;mongoose.mongodb.ProfilingLevelOptions;", // - "mongodb.ReadPreferenceFromOptions;mongodb.ReadPreferenceStatic;Member[fromOptions].Argument[0]", // - "mongodb.ReadPreferenceFromOptions;mongodb/mongodb.ReadPreferenceFromOptions;", // - "mongodb.ReadPreferenceFromOptions;mongoose.mongodb.ReadPreferenceFromOptions;", // - "mongodb.ReadPreferenceStatic;mongodb/mongodb.ReadPreferenceStatic;", // - "mongodb.ReadPreferenceStatic;mongodb;Member[ReadPreference]", // - "mongodb.ReadPreferenceStatic;mongoose.mongodb.ReadPreferenceStatic;", // - "mongodb.RemoveUserOptions;mongodb.Admin;Member[removeUser].Argument[1]", // - "mongodb.RemoveUserOptions;mongodb.Db;Member[removeUser].Argument[1]", // - "mongodb.RemoveUserOptions;mongodb/mongodb.RemoveUserOptions;", // - "mongodb.RemoveUserOptions;mongoose.mongodb.RemoveUserOptions;", // - "mongodb.RenameOptions;mongodb.Collection;Member[rename].Argument[1]", // - "mongodb.RenameOptions;mongodb.Db;Member[renameCollection].Argument[2]", // - "mongodb.RenameOptions;mongodb/mongodb.RenameOptions;", // - "mongodb.RenameOptions;mongoose.mongodb.RenameOptions;", // - "mongodb.ReplaceOptions;mongodb.Collection;Member[replaceOne].Argument[2]", // - "mongodb.ReplaceOptions;mongodb/mongodb.ReplaceOptions;", // - "mongodb.ReplaceOptions;mongoose.mongodb.ReplaceOptions;", // - "mongodb.RunCommandOptions;mongodb.Admin;Member[command].Argument[1]", // - "mongodb.RunCommandOptions;mongodb.Db;Member[command].Argument[1]", // - "mongodb.RunCommandOptions;mongodb/mongodb.RunCommandOptions;", // - "mongodb.RunCommandOptions;mongoose.mongodb.RunCommandOptions;", // - "mongodb.SelectServerOptions;mongodb/mongodb.SelectServerOptions;", // - "mongodb.SelectServerOptions;mongoose.mongodb.SelectServerOptions;", // - "mongodb.SetProfilingLevelOptions;mongodb.Db;Member[setProfilingLevel].Argument[1]", // - "mongodb.SetProfilingLevelOptions;mongodb/mongodb.SetProfilingLevelOptions;", // - "mongodb.SetProfilingLevelOptions;mongoose.mongodb.SetProfilingLevelOptions;", // - "mongodb.Transaction;mongodb.ClientSession;Member[transaction]", // - "mongodb.Transaction;mongodb.TransactionStatic;Instance", // - "mongodb.Transaction;mongodb/mongodb.Transaction;", // - "mongodb.Transaction;mongoose.mongodb.Transaction;", // - "mongodb.TransactionOptions;mongodb.ClientSession;Member[defaultTransactionOptions]", // - "mongodb.TransactionOptions;mongodb.ClientSession;Member[startTransaction].Argument[0]", // - "mongodb.TransactionOptions;mongodb.ClientSession;Member[withTransaction].Argument[1]", // - "mongodb.TransactionOptions;mongodb.ClientSessionOptions;Member[defaultTransactionOptions]", // - "mongodb.TransactionOptions;mongodb.Transaction;Member[options]", // - "mongodb.TransactionOptions;mongodb/mongodb.TransactionOptions;", // - "mongodb.TransactionOptions;mongoose.mongodb.TransactionOptions;", // - "mongodb.TransactionStatic;mongodb/mongodb.TransactionStatic;", // - "mongodb.TransactionStatic;mongodb;Member[Transaction]", // - "mongodb.TransactionStatic;mongoose.mongodb.TransactionStatic;", // - "mongodb.TypedEventEmitter;mongodb.AbstractCursor;", // - "mongodb.TypedEventEmitter;mongodb.ChangeStream;", // - "mongodb.TypedEventEmitter;mongodb.ClientSession;", // - "mongodb.TypedEventEmitter;mongodb.GridFSBucket;", // - "mongodb.TypedEventEmitter;mongodb.MongoClient;", // - "mongodb.UnorderedBulkOperation;mongodb.Collection;Member[initializeUnorderedBulkOp].ReturnValue", // - "mongodb.UnorderedBulkOperation;mongodb.UnorderedBulkOperation;Member[addToOperationsList].ReturnValue", // - "mongodb.UnorderedBulkOperation;mongodb.UnorderedBulkOperationStatic;Instance", // - "mongodb.UnorderedBulkOperation;mongodb/mongodb.UnorderedBulkOperation;", // - "mongodb.UnorderedBulkOperation;mongoose.mongodb.UnorderedBulkOperation;", // - "mongodb.UnorderedBulkOperationStatic;mongodb/mongodb.UnorderedBulkOperationStatic;", // - "mongodb.UnorderedBulkOperationStatic;mongodb;Member[UnorderedBulkOperation]", // - "mongodb.UnorderedBulkOperationStatic;mongoose.mongodb.UnorderedBulkOperationStatic;", // - "mongodb.UpdateManyModel;mongodb.AnyBulkWriteOperation;Member[updateMany]", // - "mongodb.UpdateManyModel;mongodb/mongodb.UpdateManyModel;", // - "mongodb.UpdateManyModel;mongoose.mongodb.UpdateManyModel;", // - "mongodb.UpdateOneModel;mongodb.AnyBulkWriteOperation;Member[updateOne]", // - "mongodb.UpdateOneModel;mongodb/mongodb.UpdateOneModel;", // - "mongodb.UpdateOneModel;mongoose.mongodb.UpdateOneModel;", // - "mongodb.UpdateOptions;mongodb.Collection;Member[update,updateMany,updateOne].Argument[2]", // - "mongodb.UpdateOptions;mongodb/mongodb.UpdateOptions;", // - "mongodb.UpdateOptions;mongoose.mongodb.UpdateOptions;", // - "mongodb.ValidateCollectionOptions;mongodb.Admin;Member[validateCollection].Argument[1]", // - "mongodb.ValidateCollectionOptions;mongodb/mongodb.ValidateCollectionOptions;", // - "mongodb.ValidateCollectionOptions;mongoose.mongodb.ValidateCollectionOptions;", // - "mongodb.WithSessionCallback;mongodb.MongoClient;Member[withSession].Argument[1]", // - "mongodb.WithSessionCallback;mongodb.MongoClient;Member[withSession].WithArity[1].Argument[0]", // - "mongodb.WithSessionCallback;mongodb/mongodb.WithSessionCallback;", // - "mongodb.WithSessionCallback;mongoose.mongodb.WithSessionCallback;", // - "mongodb.WithTransactionCallback;mongodb.ClientSession;Member[withTransaction].Argument[0]", // - "mongodb.WithTransactionCallback;mongodb/mongodb.WithTransactionCallback;", // - "mongodb.WithTransactionCallback;mongoose.mongodb.WithTransactionCallback;", // - "mongodb;mongoose;Member[mongodb]", // - "mongoose.AcceptsDiscriminator;mongoose.Model;", // - "mongoose.AcceptsDiscriminator;mongoose.Schema.Types.Array;", // - "mongoose.AcceptsDiscriminator;mongoose.Schema.Types.DocumentArray;", // - "mongoose.AcceptsDiscriminator;mongoose.Schema.Types.Subdocument;", // - "mongoose.Aggregate;mongoose.Aggregate;Member[addCursorFlag,addFields,allowDiskUse,append,collation,count,facet,graphLookup,group,hint,limit,lookup,match,model,near,option,project,read,readConcern,redact,replaceRoot,sample,search,session,skip,sort,sortByCount,unionWith,unwind].ReturnValue", // - "mongoose.Aggregate;mongoose.AggregateStatic;Instance", // - "mongoose.Aggregate;mongoose.Model;Member[aggregate].ReturnValue", // - "mongoose.AggregateStatic;mongoose;Member[Aggregate]", // - "mongoose.Collection;mongoose.Collection;Instance", // - "mongoose.Collection;mongoose.Connection;Member[collection].ReturnValue", // - "mongoose.Collection;mongoose.Connection;Member[collections].AnyMember", // - "mongoose.Collection;mongoose.Document;Member[collection]", // - "mongoose.Collection;mongoose.Model;Member[collection]", // - "mongoose.Collection;mongoose;Member[Collection]", // - "mongoose.CollectionBase;mongoose.Collection;", // - "mongoose.CompileModelOptions;mongoose.Connection;Member[model].Argument[3]", // - "mongoose.CompileModelOptions;mongoose;Member[model].Argument[3]", // - "mongoose.ConnectOptions;mongoose.Connection;Member[openUri].WithArity[1,2,3].Argument[1]", // - "mongoose.ConnectOptions;mongoose;Member[connect,createConnection].WithArity[1,2,3].Argument[1]", // - "mongoose.Connection;mongoose.Collection;Argument[1]", // - "mongoose.Connection;mongoose.CollectionBase;Member[conn]", // - "mongoose.Connection;mongoose.CompileModelOptions;Member[connection]", // - "mongoose.Connection;mongoose.Connection;Member[asPromise].ReturnValue.Awaited", // - "mongoose.Connection;mongoose.Connection;Member[deleteModel,plugin,setClient,useDb].ReturnValue", // - "mongoose.Connection;mongoose.Connection;Member[openUri].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.Connection;mongoose.Connection;Member[openUri].WithArity[1,2].ReturnValue.Awaited", // - "mongoose.Connection;mongoose.Connection;Member[openUri].WithArity[2,3].ReturnValue", // - "mongoose.Connection;mongoose.Connection;Member[openUri].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]", // - "mongoose.Connection;mongoose.ConnectionStatic;Instance", // - "mongoose.Connection;mongoose.Document;Member[db]", // - "mongoose.Connection;mongoose.Model;Member[db]", // - "mongoose.Connection;mongoose;Member[connection]", // - "mongoose.Connection;mongoose;Member[connections].ArrayElement", // - "mongoose.Connection;mongoose;Member[createConnection].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.Connection;mongoose;Member[createConnection].WithArity[0,1,2].ReturnValue", // - "mongoose.Connection;mongoose;Member[createConnection].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]", // - "mongoose.ConnectionStatic;mongoose;Member[Connection]", // - "mongoose.Cursor;mongoose.Query;Member[cursor].ReturnValue", // - "mongoose.DiscriminatorModel;mongoose.DiscriminatorSchema;TypeVar[mongoose.Schema.1]", // - "mongoose.Document;mongoose.Document;Member[$getAllSubdocs,$getPopulatedDocs].ReturnValue.ArrayElement", // - "mongoose.Document;mongoose.Document;Member[$inc,$parent,$set,depopulate,increment,init,overwrite,set].ReturnValue", // - "mongoose.Document;mongoose.Document;Member[delete,deleteOne].WithArity[0,1].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]", // - "mongoose.Document;mongoose.Document;Member[equals].Argument[0]", // - "mongoose.Document;mongoose.Document;Member[init].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.Document;mongoose.Document;Member[remove,save].WithArity[0,1].ReturnValue.Awaited", // - "mongoose.Document;mongoose.Document;Member[replaceOne,update,updateOne].ReturnValue.TypeVar[mongoose.Query.1]", // - "mongoose.Document;mongoose.Document;Member[save].Argument[1].TypeVar[mongoose.Callback.0]", // - "mongoose.Document;mongoose.Document;Member[save].WithArity[1].Argument[0].TypeVar[mongoose.Callback.0]", // - "mongoose.Document;mongoose.DocumentStatic;Instance", // - "mongoose.Document;mongoose.Error.VersionErrorStatic;Argument[0]", // - "mongoose.Document;mongoose.HydratedDocument;", // - "mongoose.Document;mongoose.HydratedDocument;TypeVar[mongoose.Require_id.0]", // - "mongoose.Document;mongoose.Model;Member[bulkSave].Argument[0].ArrayElement", // - "mongoose.Document;mongoose.TVirtualPathFN;Argument[2]", // - "mongoose.Document;mongoose.Types.Subdocument;", // - "mongoose.Document;mongoose.Types.Subdocument;Member[$parent,ownerDocument,parent].ReturnValue", // - "mongoose.Document;mongoose.VirtualType;Member[applyGetters,applySetters].Argument[1]", // - "mongoose.DocumentStatic;mongoose;Member[Document]", // - "mongoose.Error.VersionErrorStatic;mongoose;Member[Error].Member[VersionError]", // - "mongoose.HydratedDocument;mongoose.Model;Instance", // - "mongoose.HydratedDocument;mongoose.Model;Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,geoSearch,remove,replaceOne,update,updateMany,updateOne,where].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[$where,find,geoSearch,where].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[create,insertMany].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[create].WithArity[0..,1,2].ReturnValue.Awaited.ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[create].WithArity[1].ReturnValue.Awaited", // - "mongoose.HydratedDocument;mongoose.Model;Member[create].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[exists].WithArity[1,2].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[find,insertMany].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findById,findOne].Argument[3].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findByIdAndDelete,findByIdAndRemove,findOneAndDelete,findOneAndRemove].Argument[2].Argument[1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.ModifyResult.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findByIdAndUpdate].WithArity[0,1,2,4].Argument[3].Argument[1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findByIdAndUpdate].WithArity[3].Argument[2,3].Argument[1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findById].WithArity[1,2,3].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findOneAndReplace].WithArity[0,1,2,3,4].Argument[3].Argument[1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findOneAndUpdate].WithArity[3,4].Argument[3].Argument[1]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findOne].WithArity[0,1,2].Argument[1,2].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[findOne].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[find].Argument[3].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[find].WithArity[0].Argument[0].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[find].WithArity[1].Argument[0,1,2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[find].WithArity[2].Argument[1,2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[geoSearch].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[hydrate].ReturnValue", // - "mongoose.HydratedDocument;mongoose.Model;Member[init].ReturnValue.Awaited", // - "mongoose.HydratedDocument;mongoose.Model;Member[insertMany].WithArity[1,2].ReturnValue.Awaited.ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[populate].WithArity[2,3].Argument[2].TypeVar[mongoose.Callback.0]", // - "mongoose.HydratedDocument;mongoose.Model;Member[populate].WithArity[2,3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.HydratedDocument;mongoose.Model;Member[populate].WithArity[2,3].ReturnValue.Awaited", // - "mongoose.HydratedDocument;mongoose.Model;Member[populate].WithArity[2,3].ReturnValue.Awaited.ArrayElement", // - "mongoose.HydratedDocument;mongoose.TVirtualPathFN;Argument[1].TypeVar[mongoose.VirtualType.0]", // - "mongoose.HydratedDocument;mongoose.VirtualPathFunctions;Member[options].TypeVar[mongoose.VirtualTypeOptions.0]", // - "mongoose.InsertManyOptions;mongoose.Model;Member[insertMany].WithArity[2,3].Argument[1]", // - "mongoose.Model;mongoose.AcceptsDiscriminator;Member[discriminator].WithArity[2,3].ReturnValue", // - "mongoose.Model;mongoose.Aggregate;Member[model].Argument[0]", // - "mongoose.Model;mongoose.Connection;Member[model].WithArity[1,2,3,4].ReturnValue", // - "mongoose.Model;mongoose.Connection;Member[models].AnyMember", // - "mongoose.Model;mongoose.DiscriminatorModel;", // - "mongoose.Model;mongoose.Document;Member[$model].ReturnValue", // - "mongoose.Model;mongoose.Document;Member[populate].Argument[2]", // - "mongoose.Model;mongoose.Model;Member[discriminators].AnyMember", // - "mongoose.Model;mongoose.Models;AnyMember", // - "mongoose.Model;mongoose.PopulateOptions;Member[model]", // - "mongoose.Model;mongoose.Query;Member[cast].Argument[0]", // - "mongoose.Model;mongoose.Query;Member[populate].Argument[2]", // - "mongoose.Model;mongoose.Schema.Types.Array;Member[discriminator].WithArity[2,3].ReturnValue", // - "mongoose.Model;mongoose.Schema.Types.DocumentArray;Member[discriminator].WithArity[2,3].ReturnValue", // - "mongoose.Model;mongoose.Schema.Types.Subdocument;Member[discriminator].WithArity[2,3].ReturnValue", // - "mongoose.Model;mongoose.SchemaStatic;Instance.TypeVar[mongoose.Schema.1]", // - "mongoose.Model;mongoose;Member[Model]", // - "mongoose.Model;mongoose;Member[model].ReturnValue", // - "mongoose.Models;mongoose;Member[models]", // - "mongoose.PopulateOption;mongoose.InsertManyOptions;", // - "mongoose.PopulateOption;mongoose.QueryOptions;", // - "mongoose.PopulateOptions;mongoose.Document;Member[populate].Argument[4]", // - "mongoose.PopulateOptions;mongoose.Document;Member[populate].WithArity[1,2].Argument[0]", // - "mongoose.PopulateOptions;mongoose.Document;Member[populate].WithArity[1,2].Argument[0].ArrayElement", // - "mongoose.PopulateOptions;mongoose.Model;Member[populate].Argument[1]", // - "mongoose.PopulateOptions;mongoose.Model;Member[populate].Argument[1].ArrayElement", // - "mongoose.PopulateOptions;mongoose.PopulateOption;Member[populate]", // - "mongoose.PopulateOptions;mongoose.PopulateOption;Member[populate].ArrayElement", // - "mongoose.PopulateOptions;mongoose.PopulateOptions;Member[populate]", // - "mongoose.PopulateOptions;mongoose.PopulateOptions;Member[populate].ArrayElement", // - "mongoose.PopulateOptions;mongoose.Query;Member[populate].WithArity[1].Argument[0]", // - "mongoose.PopulateOptions;mongoose.Query;Member[populate].WithArity[1].Argument[0].ArrayElement", // - "mongoose.Query;mongoose.Document;Member[replaceOne,update,updateOne].ReturnValue", // - "mongoose.Query;mongoose.HydratedDocument;TypeVar[mongoose.Require_id.0]", // - "mongoose.Query;mongoose.Query;Member[all,allowDiskUse,and,batchSize,box,circle,clone,collation,comment,elemMatch,equals,exists,explain,geometry,gt,gte,hint,in,intersects,j,limit,lt,lte,maxDistance,maxScan,maxTimeMS,merge,mod,ne,near,nin,nor,or,polygon,read,readConcern,regex,remove,select,session,set,setOptions,size,skip,slice,snapshot,sort,tailable,w,where,within,wtimeout].ReturnValue", // - "mongoose.Query;mongoose.Query;Member[error].WithArity[1].ReturnValue", // - "mongoose.Query;mongoose.Query;Member[merge].Argument[0]", // - "mongoose.Query;mongoose.QueryStatic;Instance", // - "mongoose.Query;mongoose.QueryWithHelpers;", // - "mongoose.QueryOptions;mongoose.Document;Member[delete,deleteOne,remove].WithArity[0,1,2].Argument[0]", // - "mongoose.QueryOptions;mongoose.Document;Member[replaceOne,update,updateOne].Argument[1]", // - "mongoose.QueryOptions;mongoose.Model;Member[countDocuments,findByIdAndDelete,findByIdAndRemove,findOneAndDelete,findOneAndRemove].Argument[1]", // - "mongoose.QueryOptions;mongoose.Model;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1]", // - "mongoose.QueryOptions;mongoose.Model;Member[estimatedDocumentCount].Argument[0]", // - "mongoose.QueryOptions;mongoose.Model;Member[find,findById].WithArity[1,2,3,4].Argument[2]", // - "mongoose.QueryOptions;mongoose.Model;Member[findByIdAndUpdate,findOne,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2]", // - "mongoose.QueryOptions;mongoose.Model;Member[replaceOne,update,updateMany,updateOne].Argument[2]", // - "mongoose.QueryOptions;mongoose.PopulateOptions;Member[options]", // - "mongoose.QueryOptions;mongoose.Query;Member[countDocuments,findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[1]", // - "mongoose.QueryOptions;mongoose.Query;Member[cursor,estimatedDocumentCount,setOptions].Argument[0]", // - "mongoose.QueryOptions;mongoose.Query;Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.1]", // - "mongoose.QueryOptions;mongoose.Query;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1]", // - "mongoose.QueryOptions;mongoose.Query;Member[findByIdAndUpdate,findOne,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2]", // - "mongoose.QueryOptions;mongoose.Query;Member[find].WithArity[1,2,3,4].Argument[2]", // - "mongoose.QueryOptions;mongoose.Query;Member[getOptions].ReturnValue", // - "mongoose.QueryOptions;mongoose.Query;Member[replaceOne,update,updateMany,updateOne].Argument[2]", // - "mongoose.QueryOptions;mongoose.VirtualTypeOptions;Member[options]", // - "mongoose.QueryStatic;mongoose;Member[Query]", // - "mongoose.QueryWithHelpers;mongoose.Document;Member[delete,deleteOne].WithArity[0,1].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Model;Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove,geoSearch,remove,replaceOne,update,updateMany,updateOne,where].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Model;Member[exists].WithArity[1,2].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Model;Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Query;Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove,lean,orFail,populate,replaceOne,transform,update,updateMany,updateOne].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Query;Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue", // - "mongoose.QueryWithHelpers;mongoose.Query;Member[toConstructor].ReturnValue.Instance", // - "mongoose.Schema.Types.Array;mongoose.Schema.Types.Array;Member[enum].ReturnValue", // - "mongoose.Schema.Types.Array;mongoose.Schema.Types.ArrayStatic;Instance", // - "mongoose.Schema.Types.ArrayStatic;mongoose;Member[Schema].Member[Types].Member[Array]", // - "mongoose.Schema.Types.DocumentArray;mongoose.Schema.Types.DocumentArrayStatic;Instance", // - "mongoose.Schema.Types.DocumentArrayStatic;mongoose;Member[Schema].Member[Types].Member[DocumentArray]", // - "mongoose.Schema.Types.Subdocument;mongoose.Schema.Types.SubdocumentStatic;Instance", // - "mongoose.Schema.Types.SubdocumentStatic;mongoose.Schema.Types.DocumentArray;Member[caster]", // - "mongoose.Schema.Types.SubdocumentStatic;mongoose;Member[Schema].Member[Types].Member[Subdocument]", // - "mongoose.SchemaStatic;mongoose;Member[Schema]", // - "mongoose.SessionOperation;mongoose.Aggregate;", // - "mongoose.SessionOperation;mongoose.Query;", // - "mongoose.TVirtualPathFN;mongoose.VirtualPathFunctions;Member[get,set]", // - "mongoose.Types.Array;mongoose.Types.DocumentArray;", // - "mongoose.Types.ArraySubdocument;mongoose.Types.ArraySubdocumentStatic;Instance", // - "mongoose.Types.ArraySubdocumentStatic;mongoose;Member[Types].Member[ArraySubdocument]", // - "mongoose.Types.DocumentArray;mongoose.Types.ArraySubdocument;Member[parentArray].ReturnValue", // - "mongoose.Types.DocumentArray;mongoose.Types.DocumentArrayStatic;Instance", // - "mongoose.Types.DocumentArray;mongoose/inferschematype.ResolvePathType;TypeVar[mongoose.IfEquals.3]", // - "mongoose.Types.DocumentArrayStatic;mongoose;Member[Types].Member[DocumentArray]", // - "mongoose.Types.ObjectId;mongoose/inferschematype.ResolvePathType;", // - "mongoose.Types.Subdocument;mongoose.Types.ArraySubdocument;", // - "mongoose.Types.Subdocument;mongoose.Types.DocumentArray;Member[create,id].ReturnValue", // - "mongoose.Types.Subdocument;mongoose.Types.DocumentArray;TypeVar[mongoose.Types.Array.0]", // - "mongoose.Types.Subdocument;mongoose.Types.SubdocumentStatic;Instance", // - "mongoose.Types.SubdocumentStatic;mongoose;Member[Types].Member[Subdocument]", // - "mongoose.VirtualType;mongoose.TVirtualPathFN;Argument[1]", // - "mongoose.VirtualType;mongoose.VirtualType;Member[get,set].Argument[0].Argument[1]", // - "mongoose.VirtualType;mongoose.VirtualType;Member[get,set].ReturnValue", // - "mongoose.VirtualType;mongoose.VirtualTypeStatic;Instance", // - "mongoose.VirtualTypeOptions;mongoose.VirtualPathFunctions;Member[options]", // - "mongoose.VirtualTypeStatic;mongoose;Member[VirtualType]", // - "mongoose/inferschematype.ResolvePathType;mongoose/inferschematype.ObtainDocumentPathType;", // - "mongoose/inferschematype.ResolvePathType;mongoose/inferschematype.ResolvePathType;TypeVar[mongoose.IfEquals.3].ArrayElement", // - "mongoose/inferschematype.ResolvePathType;mongoose/inferschematype.ResolvePathType;TypeVar[mongoose.IfEquals.3].TypeVar[mongoose.Types.DocumentArray.0]", // - "mongoose;mongoose;Member[mongoose]", // - ] - } -} - -private class Summaries extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "mongodb.AbstractCursor;;;Member[addCursorFlag,batchSize,maxTimeMS,withReadConcern,withReadPreference].ReturnValue;type", // - "mongodb.BulkOperationBase;;;Member[addToOperationsList,raw].ReturnValue;type", // - "mongodb.FindCursor;;;Member[addQueryModifier,allowDiskUse,collation,comment,filter,hint,limit,max,maxAwaitTimeMS,maxTimeMS,min,returnKey,showRecordId,skip,sort].ReturnValue;type", // - "mongodb.FindOperators;;;Member[arrayFilters,collation,upsert].ReturnValue;type", // - "mongodb.GridFSBucketWriteStream;;;Member[end].ReturnValue;type", // - "mongodb.MongoClient;;;Member[connect].Argument[0].TypeVar[mongodb.Callback.0];type", // - "mongodb.MongoClient;;;Member[connect].WithArity[0].ReturnValue.Awaited;type", // - "mongodb.OrderedBulkOperation;;;Member[addToOperationsList].ReturnValue;type", // - "mongodb.TypedEventEmitter;;;Member[addListener,off,on,once,prependListener,prependOnceListener,removeAllListeners,removeListener,setMaxListeners].ReturnValue;type", // - "mongodb.UnorderedBulkOperation;;;Member[addToOperationsList].ReturnValue;type", // - "mongoose.Aggregate;;;Member[addCursorFlag,addFields,allowDiskUse,append,collation,count,facet,graphLookup,group,hint,limit,lookup,match,model,near,option,project,read,readConcern,redact,replaceRoot,sample,search,session,skip,sort,sortByCount,unionWith,unwind].ReturnValue;type", // - "mongoose.Connection;;;Member[asPromise].ReturnValue.Awaited;type", // - "mongoose.Connection;;;Member[deleteModel,setClient].ReturnValue;type", // - "mongoose.Cursor;;;Member[addCursorFlag].ReturnValue;type", // - "mongoose.Document;;;Member[$inc,$set,depopulate,increment,init,overwrite,set].ReturnValue;type", // - "mongoose.Document;;;Member[delete,deleteOne].WithArity[0,1].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1];type", // - "mongoose.Document;;;Member[getChanges].ReturnValue.TypeVar[mongoose.UpdateQuery.0];type", // - "mongoose.Document;;;Member[init].Argument[2].TypeVar[mongoose.Callback.0];type", // - "mongoose.Document;;;Member[populate].Argument[1,5].TypeVar[mongoose.Callback.0].TypeVar[mongoose.MergeType.0];type", // - "mongoose.Document;;;Member[populate].WithArity[1,2,3,4,5].ReturnValue.Awaited.TypeVar[mongoose.MergeType.0];type", // - "mongoose.Document;;;Member[remove,save].WithArity[0,1].ReturnValue.Awaited;type", // - "mongoose.Document;;;Member[replaceOne,update,updateOne].ReturnValue.TypeVar[mongoose.Query.1];type", // - "mongoose.Document;;;Member[save].Argument[1].TypeVar[mongoose.Callback.0];type", // - "mongoose.Document;;;Member[save].WithArity[1].Argument[0].TypeVar[mongoose.Callback.0];type", // - "mongoose.Document;;;Member[update,updateOne].Argument[0].TypeVar[mongoose.UpdateQuery.0];type", // - "mongoose.Query;;;Member[all,allowDiskUse,and,batchSize,box,circle,clone,collation,comment,elemMatch,equals,exists,explain,geometry,gt,gte,hint,in,intersects,j,limit,lt,lte,maxDistance,maxScan,maxTimeMS,merge,mod,ne,near,nin,nor,or,polygon,read,readConcern,regex,select,session,set,setOptions,size,skip,slice,snapshot,sort,tailable,w,where,within,wtimeout].ReturnValue;type", // - "mongoose.Query;;;Member[error].WithArity[1].ReturnValue;type", // - "mongoose.Schema.Types.Array;;;Member[enum].ReturnValue;type", // - "mongoose.SessionOperation;;;Member[session].ReturnValue;type", // - "mongoose.Types.Array;;;Member[pull,remove,set].ReturnValue;type", // - "mongoose.Types.ObjectId;;;Member[_id];type", // - "mongoose.VirtualType;;;Member[get,set].ReturnValue;type", // - ] - } -} - -private class TypeVariables extends ModelInput::TypeVariableModelCsv { - override predicate row(string row) { - row = - [ - "mongodb.Callback.0;Argument[1]", // - "mongoose.Callback.0;Argument[1]", // - "mongoose.Cursor.0;Member[eachAsync].WithArity[1,2,3].Argument[0].Argument[0]", // - "mongoose.Cursor.0;Member[eachAsync].WithArity[2,3].Argument[0].Argument[0].ArrayElement", // - "mongoose.Cursor.0;Member[map].Argument[0].Argument[0]", // - "mongoose.Cursor.0;Member[next].Argument[0].TypeVar[mongoose.Callback.0]", // - "mongoose.Cursor.0;Member[next].WithArity[0].ReturnValue.Awaited", // - "mongoose.Cursor.1;Member[map].ReturnValue.TypeVar[mongoose.Cursor.1]", // - "mongoose.Cursor.1;Member[options]", // - "mongoose.DiscriminatorSchema.1;TypeVar[mongoose.Schema.1]", // - "mongoose.DiscriminatorSchema.1;TypeVar[mongoose.Schema.1].TypeVar[mongoose.DiscriminatorModel.1]", // - "mongoose.Document.0;Member[_id]", // - "mongoose.Document.0;Member[equals].Argument[0].TypeVar[mongoose.Document.0]", // - "mongoose.FilterQuery.0;TypeVar[mongoose._FilterQuery.0]", // - "mongoose.IfAny.1;", // - "mongoose.IfAny.2;", // - "mongoose.IfEquals.3;", // - "mongoose.LeanDocumentOrArray.0;", // - "mongoose.LeanDocumentOrArray.0;TypeVar[mongoose.LeanDocument.0]", // - "mongoose.LeanDocumentOrArrayWithRawType.0;", // - "mongoose.ModifyResult.0;Member[value].TypeVar[mongoose.Require_id.0]", // - "mongoose.PluginFunction.1;Argument[0].TypeVar[mongoose.Schema.1]", // - "mongoose.PostMiddlewareFunction.1;Argument[0]", // - "mongoose.Query.0;Member[exec].Argument[0].TypeVar[mongoose.Callback.0]", // - "mongoose.Query.0;Member[exec].WithArity[0].ReturnValue.Awaited", // - "mongoose.Query.0;Member[lean].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.LeanDocumentOrArray.0,mongoose.LeanDocumentOrArrayWithRawType.0]", // - "mongoose.Query.0;Member[orFail].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0]", // - "mongoose.Query.0;Member[populate].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.UnpackedIntersection.0]", // - "mongoose.Query.0;Member[then,transform].Argument[0].Argument[0]", // - "mongoose.Query.0;Member[toConstructor].ReturnValue.Instance.TypeVar[mongoose.QueryWithHelpers.0]", // - "mongoose.Query.1;Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,lean,orFail,populate,replaceOne,transform,update,updateMany,updateOne].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]", // - "mongoose.Query.1;Member[$where,find].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].ArrayElement", // - "mongoose.Query.1;Member[_mongooseOptions].TypeVar[mongoose.MongooseQueryOptions.0]", // - "mongoose.Query.1;Member[and,nor,or].Argument[0].ArrayElement.TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[countDocuments,findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[1].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[countDocuments].WithArity[1,2,3].Argument[0].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[count].WithArity[1,2].Argument[0].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[cursor,estimatedDocumentCount,setOptions].Argument[0].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.0]", // - "mongoose.Query.1;Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.1].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[distinct].Argument[1].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]", // - "mongoose.Query.1;Member[findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[2].Argument[1]", // - "mongoose.Query.1;Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[1].TypeVar[mongoose.UpdateQuery.0]", // - "mongoose.Query.1;Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]", // - "mongoose.Query.1;Member[findByIdAndUpdate].WithArity[0,1,2,4].Argument[3].Argument[1]", // - "mongoose.Query.1;Member[findByIdAndUpdate].WithArity[3].Argument[2,3].Argument[1]", // - "mongoose.Query.1;Member[findOne,findOneAndDelete,findOneAndRemove,findOneAndUpdate,merge,remove,replaceOne,setQuery,update,updateMany,updateOne].Argument[0].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[findOneAndUpdate].Argument[3].Argument[1]", // - "mongoose.Query.1;Member[findOneAndUpdate].Argument[3].Argument[2].TypeVar[mongoose.ModifyResult.0]", // - "mongoose.Query.1;Member[findOneAndUpdate].WithArity[3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.ModifyResult.0]", // - "mongoose.Query.1;Member[findOne].Argument[3].TypeVar[mongoose.Callback.0]", // - "mongoose.Query.1;Member[findOne].WithArity[0,1,2,3].Argument[2].TypeVar[mongoose.Callback.0,mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[findOne].WithArity[0,1,2].Argument[1].TypeVar[mongoose.Callback.0,mongoose.ProjectionType.0]", // - "mongoose.Query.1;Member[findOne].WithArity[3,4].Argument[1].TypeVar[mongoose.ProjectionType.0]", // - "mongoose.Query.1;Member[findOne].WithArity[4].Argument[2].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[find].Argument[3].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.Query.1;Member[find].WithArity[0].Argument[0].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.Query.1;Member[find].WithArity[1,2,3,4].Argument[0].TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[find].WithArity[1,2,3,4].Argument[1].TypeVar[mongoose.ProjectionType.0]", // - "mongoose.Query.1;Member[find].WithArity[1,2,3,4].Argument[2].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[find].WithArity[1].Argument[0,1,2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.Query.1;Member[find].WithArity[2].Argument[1,2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.Query.1;Member[find].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement", // - "mongoose.Query.1;Member[getFilter,getQuery].ReturnValue.TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Query.1;Member[getOptions].ReturnValue.TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[getUpdate].ReturnValue.TypeVar[mongoose.UpdateQuery.0]", // - "mongoose.Query.1;Member[projection].WithArity[0,1].Argument[0].TypeVar[mongoose.ProjectionFields.0]", // - "mongoose.Query.1;Member[projection].WithArity[0,1].ReturnValue.TypeVar[mongoose.ProjectionFields.0]", // - "mongoose.Query.1;Member[remove].ReturnValue.TypeVar[mongoose.Query.1]", // - "mongoose.Query.1;Member[replaceOne,update,updateMany,updateOne].Argument[2].TypeVar[mongoose.QueryOptions.0]", // - "mongoose.Query.1;Member[replaceOne].Argument[1]", // - "mongoose.Query.1;Member[setUpdate].Argument[0].TypeVar[mongoose.UpdateQuery.0]", // - "mongoose.Query.1;Member[toConstructor].ReturnValue.Instance.TypeVar[mongoose.QueryWithHelpers.1]", // - "mongoose.QueryOptions.0;Member[projection].TypeVar[mongoose.ProjectionType.0]", // - "mongoose.QueryWithHelpers.0;TypeVar[mongoose.Query.0]", // - "mongoose.QueryWithHelpers.1;TypeVar[mongoose.Query.1]", // - "mongoose.Require_id.0;", // - "mongoose.Require_id.0;TypeVar[mongoose.IfAny.1,mongoose.IfAny.2]", // - "mongoose.RootQuerySelector.0;Member[$and,$nor,$or].ArrayElement.TypeVar[mongoose.FilterQuery.0]", // - "mongoose.Schema.1;Member[discriminator].ReturnValue.TypeVar[mongoose.DiscriminatorSchema.1]", // - "mongoose.Schema.1;Member[plugin].Argument[0].TypeVar[mongoose.PluginFunction.1]", // - "mongoose.Schema.1;Member[post].Argument[2].TypeVar[mongoose.ErrorHandlingMiddlewareFunction.0,mongoose.PostMiddlewareFunction.0,mongoose.PostMiddlewareFunction.1]", // - "mongoose.Schema.1;Member[post].WithArity[2].WithStringArgument[0=insertMany].Argument[1].TypeVar[mongoose.ErrorHandlingMiddlewareFunction.0,mongoose.PostMiddlewareFunction.0,mongoose.PostMiddlewareFunction.1]", // - "mongoose.Types.Array.0;Member[$pop,$shift,shift].ReturnValue", // - "mongoose.Types.Array.0;Member[set].Argument[1]", // - "mongoose.Types.DocumentArray.0;Member[create,id].ReturnValue", // - "mongoose.Types.DocumentArray.0;Member[create,id].ReturnValue.TypeVar[mongoose.Types.Subdocument.0].TypeVar[mongoose.InferId.0]", // - "mongoose.Types.DocumentArray.0;Member[push].Argument[0].ArrayElement.TypeVar[mongoose.AnyKeys.0]", // - "mongoose.Types.DocumentArray.0;TypeVar[mongoose.Types.Array.0]", // - "mongoose.Types.DocumentArray.0;TypeVar[mongoose.Types.Array.0].TypeVar[mongoose.Types.Subdocument.0].TypeVar[mongoose.InferId.0]", // - "mongoose.Types.Subdocument.0;TypeVar[mongoose.Document.0]", // - "mongoose.UnpackedIntersection.0;", // - "mongoose.UpdateQuery.0;TypeVar[mongoose._UpdateQuery.0].TypeVar[mongoose._UpdateQueryDef.0]", // - "mongoose.VirtualType.0;Member[get,set].Argument[0].Argument[1].TypeVar[mongoose.VirtualType.0]", // - "mongoose.VirtualType.0;Member[get,set].Argument[0].Argument[2]", // - "mongoose.VirtualTypeOptions.0;Member[foreignField,localField].Argument[0]", // - "mongoose._FilterQuery.0;TypeVar[mongoose.RootQuerySelector.0]", // - "mongoose._UpdateQuery.0;Member[$currentDate,$inc,$max,$min,$mul,$pop,$pull,$pullAll,$push,$set,$setOnInsert,$unset].TypeVar[mongoose.AnyKeys.0]", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mongodb/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/mongodb/model.yml new file mode 100644 index 00000000000..e2f3f20ee29 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/mongodb/model.yml @@ -0,0 +1,791 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - [mongodb.Collection, "Member[aggregate,count,countDocuments,deleteMany,deleteOne,find,findOne,findOneAndDelete,findOneAndReplace,remove,replaceOne,watch].Argument[0]", mongodb.sink] + - [mongodb.Collection, "Member[distinct].Argument[1]", mongodb.sink] + - [mongodb.Collection, "Member[findOneAndUpdate,update,updateMany,updateOne].Argument[0,1]", mongodb.sink] + - [mongodb.Db, "Member[aggregate,watch].Argument[0]", mongodb.sink] + - [mongodb.DeleteManyModel, "Member[filter]", mongodb.sink] + - [mongodb.DeleteOneModel, "Member[filter]", mongodb.sink] + - [mongodb.MongoClient, "Member[watch].Argument[0]", mongodb.sink] + - [mongodb.UpdateManyModel, "Member[filter,update]", mongodb.sink] + - [mongodb.UpdateOneModel, "Member[filter,update]", mongodb.sink] + - [mongoose.CollectionBase, "Member[findAndModify].Argument[0]", mongodb.sink] + - [mongoose.Connection, "Member[watch].Argument[0]", mongodb.sink] + - [mongoose.Document, "Member[update,updateOne].Argument[0]", mongodb.sink] + - [mongoose.Model, "Member[$where,aggregate,exists,find,findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove,findOneAndReplace,geoSearch,remove,replaceOne,watch].Argument[0]", mongodb.sink] + - [mongoose.Model, "Member[count,where].WithArity[1,2].Argument[0]", mongodb.sink] + - [mongoose.Model, "Member[countDocuments].WithArity[1,2,3].Argument[0]", mongodb.sink] + - [mongoose.Model, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0]", mongodb.sink] + - [mongoose.Model, "Member[distinct,where].Argument[1]", mongodb.sink] + - [mongoose.Model, "Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[0,1]", mongodb.sink] + - [mongoose.Model, "Member[find].WithArity[1,2,3,4].Argument[0]", mongodb.sink] + - [mongoose.Query, "Member[$where,and,find,findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove,nor,or,remove,replaceOne,setUpdate].Argument[0]", mongodb.sink] + - [mongoose.Query, "Member[count,where].WithArity[1,2].Argument[0]", mongodb.sink] + - [mongoose.Query, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0]", mongodb.sink] + - [mongoose.Query, "Member[distinct,where].Argument[1]", mongodb.sink] + - [mongoose.Query, "Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[0,1]", mongodb.sink] + - [mongoose.Query, "Member[find].WithArity[1,2,3,4].Argument[0]", mongodb.sink] + - [mongoose.QueryStatic, "Argument[2]", mongodb.sink] + + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [mongodb.AbstractCursor, mongodb.FindCursor, ""] + - [mongodb.AbstractCursor, mongodb.ListCollectionsCursor, ""] + - [mongodb.AbstractCursor, mongodb.ListIndexesCursor, ""] + - [mongodb.AbstractCursorOptions, mongodb.AggregationCursorOptions, ""] + - [mongodb.AbstractCursorOptions, "mongodb/mongodb.AbstractCursorOptions", ""] + - [mongodb.AbstractCursorOptions, mongoose.mongodb.AbstractCursorOptions, ""] + - [mongodb.AddUserOptions, mongodb.Admin, "Member[addUser].Argument[1,2]"] + - [mongodb.AddUserOptions, mongodb.Db, "Member[addUser].Argument[1,2]"] + - [mongodb.AddUserOptions, "mongodb/mongodb.AddUserOptions", ""] + - [mongodb.AddUserOptions, mongoose.mongodb.AddUserOptions, ""] + - [mongodb.Admin, mongodb.AdminStatic, Instance] + - [mongodb.Admin, mongodb.Db, "Member[admin].ReturnValue"] + - [mongodb.Admin, "mongodb/mongodb.Admin", ""] + - [mongodb.Admin, mongoose.mongodb.Admin, ""] + - [mongodb.AdminStatic, "mongodb/mongodb.AdminStatic", ""] + - [mongodb.AdminStatic, mongodb, "Member[Admin]"] + - [mongodb.AdminStatic, mongoose.mongodb.AdminStatic, ""] + - [mongodb.AggregateOptions, mongodb.AggregationCursorOptions, ""] + - [mongodb.AggregateOptions, mongodb.ChangeStreamOptions, ""] + - [mongodb.AggregateOptions, mongodb.Collection, "Member[aggregate].Argument[1]"] + - [mongodb.AggregateOptions, mongodb.CountDocumentsOptions, ""] + - [mongodb.AggregateOptions, mongodb.Db, "Member[aggregate].Argument[1]"] + - [mongodb.AggregateOptions, "mongodb/mongodb.AggregateOptions", ""] + - [mongodb.AggregateOptions, mongoose.mongodb.AggregateOptions, ""] + - [mongodb.AggregationCursorOptions, "mongodb/mongodb.AggregationCursorOptions", ""] + - [mongodb.AggregationCursorOptions, mongoose.mongodb.AggregationCursorOptions, ""] + - [mongodb.AnyBulkWriteOperation, mongodb.BulkOperationBase, "Member[raw].Argument[0]"] + - [mongodb.AnyBulkWriteOperation, mongodb.Collection, "Member[bulkWrite].Argument[0].ArrayElement"] + - [mongodb.AnyBulkWriteOperation, "mongodb/mongodb.AnyBulkWriteOperation", ""] + - [mongodb.AnyBulkWriteOperation, mongoose.mongodb.AnyBulkWriteOperation, ""] + - [mongodb.Auth, mongodb.MongoClientOptions, "Member[auth]"] + - [mongodb.Auth, "mongodb/mongodb.Auth", ""] + - [mongodb.Auth, mongoose.mongodb.Auth, ""] + - [mongodb.AutoEncrypter, mongodb.AutoEncrypter, Instance] + - [mongodb.AutoEncrypter, mongodb.ConnectionOptions, "Member[autoEncrypter]"] + - [mongodb.AutoEncrypter, mongodb.MongoClient, "Member[autoEncrypter]"] + - [mongodb.AutoEncrypter, mongodb.MongoOptions, "Member[autoEncrypter]"] + - [mongodb.AutoEncrypter, "mongodb/mongodb.AutoEncrypter", ""] + - [mongodb.AutoEncrypter, mongoose.mongodb.AutoEncrypter, ""] + - [mongodb.AutoEncryptionOptions, mongodb.AutoEncrypter, "Argument[1]"] + - [mongodb.AutoEncryptionOptions, mongodb.MongoClientOptions, "Member[autoEncryption]"] + - [mongodb.AutoEncryptionOptions, "mongodb/mongodb.AutoEncryptionOptions", ""] + - [mongodb.AutoEncryptionOptions, mongoose.mongodb.AutoEncryptionOptions, ""] + - [mongodb.BulkOperationBase, mongodb.BulkOperationBase, "Member[addToOperationsList,insert,raw].ReturnValue"] + - [mongodb.BulkOperationBase, mongodb.BulkOperationBaseStatic, Instance] + - [mongodb.BulkOperationBase, mongodb.FindOperators, "Member[bulkOperation]"] + - [mongodb.BulkOperationBase, mongodb.FindOperators, "Member[delete,deleteOne,replaceOne,update,updateOne].ReturnValue"] + - [mongodb.BulkOperationBase, mongodb.OrderedBulkOperation, ""] + - [mongodb.BulkOperationBase, mongodb.UnorderedBulkOperation, ""] + - [mongodb.BulkOperationBase, "mongodb/mongodb.BulkOperationBase", ""] + - [mongodb.BulkOperationBase, mongoose.mongodb.BulkOperationBase, ""] + - [mongodb.BulkOperationBaseStatic, "mongodb/mongodb.BulkOperationBaseStatic", ""] + - [mongodb.BulkOperationBaseStatic, mongodb, "Member[BulkOperationBase]"] + - [mongodb.BulkOperationBaseStatic, mongoose.mongodb.BulkOperationBaseStatic, ""] + - [mongodb.BulkWriteOptions, mongodb.BulkOperationBase, "Member[execute].WithArity[0,1,2].Argument[0]"] + - [mongodb.BulkWriteOptions, mongodb.Collection, "Member[bulkWrite,insert,insertMany].Argument[1]"] + - [mongodb.BulkWriteOptions, mongodb.Collection, "Member[initializeOrderedBulkOp,initializeUnorderedBulkOp].Argument[0]"] + - [mongodb.BulkWriteOptions, mongodb.OrderedBulkOperationStatic, "Argument[1]"] + - [mongodb.BulkWriteOptions, mongodb.UnorderedBulkOperationStatic, "Argument[1]"] + - [mongodb.BulkWriteOptions, "mongodb/mongodb.BulkWriteOptions", ""] + - [mongodb.BulkWriteOptions, mongoose.mongodb.BulkWriteOptions, ""] + - [mongodb.ChangeStream, mongodb.ChangeStreamStatic, Instance] + - [mongodb.ChangeStream, mongodb.Collection, "Member[watch].ReturnValue"] + - [mongodb.ChangeStream, mongodb.Db, "Member[watch].ReturnValue"] + - [mongodb.ChangeStream, mongodb.MongoClient, "Member[watch].ReturnValue"] + - [mongodb.ChangeStream, "mongodb/mongodb.ChangeStream", ""] + - [mongodb.ChangeStream, mongoose.mongodb.ChangeStream, ""] + - [mongodb.ChangeStreamOptions, mongodb.ChangeStream, "Member[options]"] + - [mongodb.ChangeStreamOptions, mongodb.Collection, "Member[watch].Argument[1]"] + - [mongodb.ChangeStreamOptions, mongodb.Db, "Member[watch].Argument[1]"] + - [mongodb.ChangeStreamOptions, mongodb.MongoClient, "Member[watch].Argument[1]"] + - [mongodb.ChangeStreamOptions, "mongodb/mongodb.ChangeStreamOptions", ""] + - [mongodb.ChangeStreamOptions, mongoose.mongodb.ChangeStreamOptions, ""] + - [mongodb.ChangeStreamStatic, "mongodb/mongodb.ChangeStreamStatic", ""] + - [mongodb.ChangeStreamStatic, mongodb, "Member[ChangeStream]"] + - [mongodb.ChangeStreamStatic, mongoose.mongodb.ChangeStreamStatic, ""] + - [mongodb.ClientSession, mongodb.AbstractCursorOptions, "Member[session]"] + - [mongodb.ClientSession, mongodb.ClientSession, "Member[equals].Argument[0]"] + - [mongodb.ClientSession, mongodb.ClientSessionEvents, "Member[ended].Argument[0]"] + - [mongodb.ClientSession, mongodb.ClientSessionStatic, Instance] + - [mongodb.ClientSession, mongodb.IndexInformationOptions, "Member[session]"] + - [mongodb.ClientSession, mongodb.MongoClient, "Member[startSession].ReturnValue"] + - [mongodb.ClientSession, mongodb.OperationOptions, "Member[session]"] + - [mongodb.ClientSession, mongodb.ReadPreferenceFromOptions, "Member[session]"] + - [mongodb.ClientSession, mongodb.SelectServerOptions, "Member[session]"] + - [mongodb.ClientSession, mongodb.WithSessionCallback, "Argument[0]"] + - [mongodb.ClientSession, mongodb.WithTransactionCallback, "Argument[0]"] + - [mongodb.ClientSession, "mongodb/mongodb.ClientSession", ""] + - [mongodb.ClientSession, mongoose.mongodb.ClientSession, ""] + - [mongodb.ClientSessionEvents, "mongodb/mongodb.ClientSessionEvents", ""] + - [mongodb.ClientSessionEvents, mongoose.mongodb.ClientSessionEvents, ""] + - [mongodb.ClientSessionOptions, mongodb.MongoClient, "Member[startSession].Argument[0]"] + - [mongodb.ClientSessionOptions, mongodb.MongoClient, "Member[withSession].WithArity[2].Argument[0]"] + - [mongodb.ClientSessionOptions, "mongodb/mongodb.ClientSessionOptions", ""] + - [mongodb.ClientSessionOptions, mongoose.mongodb.ClientSessionOptions, ""] + - [mongodb.ClientSessionStatic, "mongodb/mongodb.ClientSessionStatic", ""] + - [mongodb.ClientSessionStatic, mongodb, "Member[ClientSession]"] + - [mongodb.ClientSessionStatic, mongoose.mongodb.ClientSessionStatic, ""] + - [mongodb.CollStatsOptions, mongodb.Collection, "Member[stats].Argument[0]"] + - [mongodb.CollStatsOptions, "mongodb/mongodb.CollStatsOptions", ""] + - [mongodb.CollStatsOptions, mongoose.mongodb.CollStatsOptions, ""] + - [mongodb.Collection, mongodb.ChangeStream, "Member[parent]"] + - [mongodb.Collection, mongodb.Collection, "Member[rename].Argument[1,2].TypeVar[mongodb.Callback.0]"] + - [mongodb.Collection, mongodb.Collection, "Member[rename].WithArity[1,2].ReturnValue.Awaited"] + - [mongodb.Collection, mongodb.CollectionStatic, Instance] + - [mongodb.Collection, mongodb.Db, "Member[collection].ReturnValue"] + - [mongodb.Collection, mongodb.Db, "Member[collections].Argument[0,1].TypeVar[mongodb.Callback.0].ArrayElement"] + - [mongodb.Collection, mongodb.Db, "Member[collections].WithArity[0,1].ReturnValue.Awaited.ArrayElement"] + - [mongodb.Collection, mongodb.Db, "Member[createCollection].Argument[2].TypeVar[mongodb.Callback.0]"] + - [mongodb.Collection, mongodb.Db, "Member[createCollection].WithArity[1,2].ReturnValue.Awaited"] + - [mongodb.Collection, mongodb.Db, "Member[createCollection].WithArity[2].Argument[1].TypeVar[mongodb.Callback.0]"] + - [mongodb.Collection, mongodb.Db, "Member[renameCollection].Argument[2,3].TypeVar[mongodb.Callback.0]"] + - [mongodb.Collection, mongodb.Db, "Member[renameCollection].WithArity[2,3].ReturnValue.Awaited"] + - [mongodb.Collection, mongodb.GridFSBucketWriteStream, "Member[chunks,files]"] + - [mongodb.Collection, mongodb.ListIndexesCursor, "Member[parent]"] + - [mongodb.Collection, mongodb.ListIndexesCursorStatic, "Argument[0]"] + - [mongodb.Collection, mongodb.OrderedBulkOperationStatic, "Argument[0]"] + - [mongodb.Collection, mongodb.UnorderedBulkOperationStatic, "Argument[0]"] + - [mongodb.Collection, "mongodb/mongodb.Collection", ""] + - [mongodb.Collection, mongoose.mongodb.Collection, ""] + - [mongodb.CollectionStatic, "mongodb/mongodb.CollectionStatic", ""] + - [mongodb.CollectionStatic, mongodb, "Member[Collection]"] + - [mongodb.CollectionStatic, mongoose.mongodb.CollectionStatic, ""] + - [mongodb.CommandOperationOptions, mongodb.AddUserOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.Admin, "Member[buildInfo,ping,replSetGetStatus,serverInfo,serverStatus].Argument[0]"] + - [mongodb.CommandOperationOptions, mongodb.AggregateOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.BulkWriteOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.CollStatsOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.CountOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.CreateCollectionOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.CreateIndexesOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DbStatsOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DeleteOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DistinctOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DropCollectionOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DropDatabaseOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.DropIndexesOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.EstimatedDocumentCountOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.EvalOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.FindOneAndDeleteOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.FindOneAndReplaceOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.FindOneAndUpdateOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.FindOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.InsertOneOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ListCollectionsOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ListDatabasesOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ListIndexesOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.MapReduceOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ProfilingLevelOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.RemoveUserOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.RenameOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ReplaceOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.RunCommandOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.SetProfilingLevelOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.TransactionOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.UpdateOptions, ""] + - [mongodb.CommandOperationOptions, mongodb.ValidateCollectionOptions, ""] + - [mongodb.CommandOperationOptions, "mongodb/mongodb.CommandOperationOptions", ""] + - [mongodb.CommandOperationOptions, mongoose.mongodb.CommandOperationOptions, ""] + - [mongodb.ConnectionOptions, "mongodb/mongodb.ConnectionOptions", ""] + - [mongodb.ConnectionOptions, mongoose.mongodb.ConnectionOptions, ""] + - [mongodb.CountDocumentsOptions, mongodb.Collection, "Member[countDocuments].Argument[1]"] + - [mongodb.CountDocumentsOptions, "mongodb/mongodb.CountDocumentsOptions", ""] + - [mongodb.CountDocumentsOptions, mongoose.mongodb.CountDocumentsOptions, ""] + - [mongodb.CountOptions, mongodb.Collection, "Member[count].Argument[1]"] + - [mongodb.CountOptions, mongodb.FindCursor, "Member[count].Argument[0]"] + - [mongodb.CountOptions, "mongodb/mongodb.CountOptions", ""] + - [mongodb.CountOptions, mongoose.mongodb.CountOptions, ""] + - [mongodb.CreateCollectionOptions, mongodb.Db, "Member[createCollection].WithArity[1,2,3].Argument[1]"] + - [mongodb.CreateCollectionOptions, "mongodb/mongodb.CreateCollectionOptions", ""] + - [mongodb.CreateCollectionOptions, mongoose.mongodb.CreateCollectionOptions, ""] + - [mongodb.CreateIndexesOptions, mongodb.Collection, "Member[createIndex,createIndexes].Argument[1]"] + - [mongodb.CreateIndexesOptions, mongodb.Db, "Member[createIndex].Argument[2]"] + - [mongodb.CreateIndexesOptions, "mongodb/mongodb.CreateIndexesOptions", ""] + - [mongodb.CreateIndexesOptions, mongoose.mongodb.CreateIndexesOptions, ""] + - [mongodb.Db, mongodb.ChangeStream, "Member[parent]"] + - [mongodb.Db, mongodb.DbStatic, Instance] + - [mongodb.Db, mongodb.GridFSBucketStatic, "Argument[0]"] + - [mongodb.Db, mongodb.ListCollectionsCursor, "Member[parent]"] + - [mongodb.Db, mongodb.ListCollectionsCursorStatic, "Argument[0]"] + - [mongodb.Db, mongodb.MongoClient, "Member[db].ReturnValue"] + - [mongodb.Db, "mongodb/mongodb.Db", ""] + - [mongodb.Db, mongoose.mongodb.Db, ""] + - [mongodb.DbStatic, "mongodb/mongodb.DbStatic", ""] + - [mongodb.DbStatic, mongodb, "Member[Db]"] + - [mongodb.DbStatic, mongoose.mongodb.DbStatic, ""] + - [mongodb.DbStatsOptions, mongodb.Db, "Member[stats].Argument[0]"] + - [mongodb.DbStatsOptions, "mongodb/mongodb.DbStatsOptions", ""] + - [mongodb.DbStatsOptions, mongoose.mongodb.DbStatsOptions, ""] + - [mongodb.DeleteManyModel, mongodb.AnyBulkWriteOperation, "Member[deleteMany]"] + - [mongodb.DeleteManyModel, "mongodb/mongodb.DeleteManyModel", ""] + - [mongodb.DeleteManyModel, mongoose.mongodb.DeleteManyModel, ""] + - [mongodb.DeleteOneModel, mongodb.AnyBulkWriteOperation, "Member[deleteOne]"] + - [mongodb.DeleteOneModel, "mongodb/mongodb.DeleteOneModel", ""] + - [mongodb.DeleteOneModel, mongoose.mongodb.DeleteOneModel, ""] + - [mongodb.DeleteOptions, mongodb.Collection, "Member[deleteMany,deleteOne,remove].Argument[1]"] + - [mongodb.DeleteOptions, "mongodb/mongodb.DeleteOptions", ""] + - [mongodb.DeleteOptions, mongoose.mongodb.DeleteOptions, ""] + - [mongodb.DistinctOptions, mongodb.Collection, "Member[distinct].Argument[2]"] + - [mongodb.DistinctOptions, "mongodb/mongodb.DistinctOptions", ""] + - [mongodb.DistinctOptions, mongoose.mongodb.DistinctOptions, ""] + - [mongodb.DropCollectionOptions, mongodb.Collection, "Member[drop].Argument[0]"] + - [mongodb.DropCollectionOptions, mongodb.Db, "Member[dropCollection].Argument[1]"] + - [mongodb.DropCollectionOptions, "mongodb/mongodb.DropCollectionOptions", ""] + - [mongodb.DropCollectionOptions, mongoose.mongodb.DropCollectionOptions, ""] + - [mongodb.DropDatabaseOptions, mongodb.Db, "Member[dropDatabase].Argument[0]"] + - [mongodb.DropDatabaseOptions, "mongodb/mongodb.DropDatabaseOptions", ""] + - [mongodb.DropDatabaseOptions, mongoose.mongodb.DropDatabaseOptions, ""] + - [mongodb.DropIndexesOptions, mongodb.Collection, "Member[dropIndex].Argument[1]"] + - [mongodb.DropIndexesOptions, mongodb.Collection, "Member[dropIndexes].Argument[0]"] + - [mongodb.DropIndexesOptions, "mongodb/mongodb.DropIndexesOptions", ""] + - [mongodb.DropIndexesOptions, mongoose.mongodb.DropIndexesOptions, ""] + - [mongodb.EstimatedDocumentCountOptions, mongodb.Collection, "Member[estimatedDocumentCount].Argument[0]"] + - [mongodb.EstimatedDocumentCountOptions, "mongodb/mongodb.EstimatedDocumentCountOptions", ""] + - [mongodb.EstimatedDocumentCountOptions, mongoose.mongodb.EstimatedDocumentCountOptions, ""] + - [mongodb.EvalOptions, "mongodb/mongodb.EvalOptions", ""] + - [mongodb.EvalOptions, mongoose.mongodb.EvalOptions, ""] + - [mongodb.FindCursor, mongodb.Collection, "Member[find].WithArity[0,1,2].ReturnValue"] + - [mongodb.FindCursor, mongodb.FindCursor, "Member[addQueryModifier,allowDiskUse,clone,collation,comment,filter,hint,limit,map,max,maxAwaitTimeMS,maxTimeMS,min,project,returnKey,showRecordId,skip,sort].ReturnValue"] + - [mongodb.FindCursor, mongodb.FindCursorStatic, Instance] + - [mongodb.FindCursor, mongodb.GridFSBucket, "Member[find].ReturnValue"] + - [mongodb.FindCursor, "mongodb/mongodb.FindCursor", ""] + - [mongodb.FindCursor, mongoose.mongodb.FindCursor, ""] + - [mongodb.FindCursorStatic, "mongodb/mongodb.FindCursorStatic", ""] + - [mongodb.FindCursorStatic, mongodb, "Member[FindCursor]"] + - [mongodb.FindCursorStatic, mongoose.mongodb.FindCursorStatic, ""] + - [mongodb.FindOneAndDeleteOptions, mongodb.Collection, "Member[findOneAndDelete].Argument[1]"] + - [mongodb.FindOneAndDeleteOptions, "mongodb/mongodb.FindOneAndDeleteOptions", ""] + - [mongodb.FindOneAndDeleteOptions, mongoose.mongodb.FindOneAndDeleteOptions, ""] + - [mongodb.FindOneAndReplaceOptions, mongodb.Collection, "Member[findOneAndReplace].Argument[2]"] + - [mongodb.FindOneAndReplaceOptions, "mongodb/mongodb.FindOneAndReplaceOptions", ""] + - [mongodb.FindOneAndReplaceOptions, mongoose.mongodb.FindOneAndReplaceOptions, ""] + - [mongodb.FindOneAndUpdateOptions, mongodb.Collection, "Member[findOneAndUpdate].Argument[2]"] + - [mongodb.FindOneAndUpdateOptions, "mongodb/mongodb.FindOneAndUpdateOptions", ""] + - [mongodb.FindOneAndUpdateOptions, mongoose.mongodb.FindOneAndUpdateOptions, ""] + - [mongodb.FindOperators, mongodb.BulkOperationBase, "Member[find].ReturnValue"] + - [mongodb.FindOperators, mongodb.FindOperators, "Member[arrayFilters,collation,upsert].ReturnValue"] + - [mongodb.FindOperators, mongodb.FindOperatorsStatic, Instance] + - [mongodb.FindOperators, "mongodb/mongodb.FindOperators", ""] + - [mongodb.FindOperators, mongoose.mongodb.FindOperators, ""] + - [mongodb.FindOperatorsStatic, "mongodb/mongodb.FindOperatorsStatic", ""] + - [mongodb.FindOperatorsStatic, mongodb, "Member[FindOperators]"] + - [mongodb.FindOperatorsStatic, mongoose.mongodb.FindOperatorsStatic, ""] + - [mongodb.FindOptions, mongodb.Collection, "Member[find,findOne].Argument[1]"] + - [mongodb.FindOptions, mongodb.GridFSBucket, "Member[find].Argument[1]"] + - [mongodb.FindOptions, "mongodb/mongodb.FindOptions", ""] + - [mongodb.FindOptions, mongoose.mongodb.FindOptions, ""] + - [mongodb.GridFSBucket, mongodb.GridFSBucketStatic, Instance] + - [mongodb.GridFSBucket, mongodb.GridFSBucketWriteStream, "Member[bucket]"] + - [mongodb.GridFSBucket, "mongodb/mongodb.GridFSBucket", ""] + - [mongodb.GridFSBucket, mongoose.mongodb.GridFSBucket, ""] + - [mongodb.GridFSBucketStatic, "mongodb/mongodb.GridFSBucketStatic", ""] + - [mongodb.GridFSBucketStatic, mongodb, "Member[GridFSBucket]"] + - [mongodb.GridFSBucketStatic, mongoose.mongodb.GridFSBucketStatic, ""] + - [mongodb.GridFSBucketWriteStream, mongodb.GridFSBucket, "Member[openUploadStream,openUploadStreamWithId].ReturnValue"] + - [mongodb.GridFSBucketWriteStream, mongodb.GridFSBucketWriteStream, "Member[end].ReturnValue"] + - [mongodb.GridFSBucketWriteStream, mongodb.GridFSBucketWriteStreamStatic, Instance] + - [mongodb.GridFSBucketWriteStream, "mongodb/mongodb.GridFSBucketWriteStream", ""] + - [mongodb.GridFSBucketWriteStream, mongoose.mongodb.GridFSBucketWriteStream, ""] + - [mongodb.GridFSBucketWriteStreamStatic, "mongodb/mongodb.GridFSBucketWriteStreamStatic", ""] + - [mongodb.GridFSBucketWriteStreamStatic, mongodb, "Member[GridFSBucketWriteStream]"] + - [mongodb.GridFSBucketWriteStreamStatic, mongoose.mongodb.GridFSBucketWriteStreamStatic, ""] + - [mongodb.IndexInformationOptions, mongodb.Collection, "Member[indexExists].Argument[1]"] + - [mongodb.IndexInformationOptions, mongodb.Collection, "Member[indexInformation,indexes].Argument[0]"] + - [mongodb.IndexInformationOptions, mongodb.Db, "Member[indexInformation].Argument[1]"] + - [mongodb.IndexInformationOptions, "mongodb/mongodb.IndexInformationOptions", ""] + - [mongodb.IndexInformationOptions, mongoose.mongodb.IndexInformationOptions, ""] + - [mongodb.InsertOneOptions, mongodb.Collection, "Member[insertOne].Argument[1]"] + - [mongodb.InsertOneOptions, "mongodb/mongodb.InsertOneOptions", ""] + - [mongodb.InsertOneOptions, mongoose.mongodb.InsertOneOptions, ""] + - [mongodb.ListCollectionsCursor, mongodb.Db, "Member[listCollections].WithArity[0,1,2].ReturnValue"] + - [mongodb.ListCollectionsCursor, mongodb.ListCollectionsCursor, "Member[clone].ReturnValue"] + - [mongodb.ListCollectionsCursor, mongodb.ListCollectionsCursorStatic, Instance] + - [mongodb.ListCollectionsCursor, "mongodb/mongodb.ListCollectionsCursor", ""] + - [mongodb.ListCollectionsCursor, mongoose.mongodb.ListCollectionsCursor, ""] + - [mongodb.ListCollectionsCursorStatic, "mongodb/mongodb.ListCollectionsCursorStatic", ""] + - [mongodb.ListCollectionsCursorStatic, mongodb, "Member[ListCollectionsCursor]"] + - [mongodb.ListCollectionsCursorStatic, mongoose.mongodb.ListCollectionsCursorStatic, ""] + - [mongodb.ListCollectionsOptions, mongodb.Db, "Member[collections].Argument[0]"] + - [mongodb.ListCollectionsOptions, mongodb.Db, "Member[listCollections].WithArity[0,1,2].Argument[1]"] + - [mongodb.ListCollectionsOptions, mongodb.ListCollectionsCursor, "Member[options]"] + - [mongodb.ListCollectionsOptions, mongodb.ListCollectionsCursorStatic, "Argument[2]"] + - [mongodb.ListCollectionsOptions, "mongodb/mongodb.ListCollectionsOptions", ""] + - [mongodb.ListCollectionsOptions, mongoose.mongodb.ListCollectionsOptions, ""] + - [mongodb.ListDatabasesOptions, mongodb.Admin, "Member[listDatabases].Argument[0]"] + - [mongodb.ListDatabasesOptions, "mongodb/mongodb.ListDatabasesOptions", ""] + - [mongodb.ListDatabasesOptions, mongoose.mongodb.ListDatabasesOptions, ""] + - [mongodb.ListIndexesCursor, mongodb.Collection, "Member[listIndexes].ReturnValue"] + - [mongodb.ListIndexesCursor, mongodb.ListIndexesCursor, "Member[clone].ReturnValue"] + - [mongodb.ListIndexesCursor, mongodb.ListIndexesCursorStatic, Instance] + - [mongodb.ListIndexesCursor, "mongodb/mongodb.ListIndexesCursor", ""] + - [mongodb.ListIndexesCursor, mongoose.mongodb.ListIndexesCursor, ""] + - [mongodb.ListIndexesCursorStatic, "mongodb/mongodb.ListIndexesCursorStatic", ""] + - [mongodb.ListIndexesCursorStatic, mongodb, "Member[ListIndexesCursor]"] + - [mongodb.ListIndexesCursorStatic, mongoose.mongodb.ListIndexesCursorStatic, ""] + - [mongodb.ListIndexesOptions, mongodb.Collection, "Member[listIndexes].Argument[0]"] + - [mongodb.ListIndexesOptions, mongodb.ListIndexesCursor, "Member[options]"] + - [mongodb.ListIndexesOptions, mongodb.ListIndexesCursorStatic, "Argument[1]"] + - [mongodb.ListIndexesOptions, "mongodb/mongodb.ListIndexesOptions", ""] + - [mongodb.ListIndexesOptions, mongoose.mongodb.ListIndexesOptions, ""] + - [mongodb.MapReduceOptions, mongodb.Collection, "Member[mapReduce].Argument[2]"] + - [mongodb.MapReduceOptions, "mongodb/mongodb.MapReduceOptions", ""] + - [mongodb.MapReduceOptions, mongoose.mongodb.MapReduceOptions, ""] + - [mongodb.MongoClient, mongodb.AutoEncrypter, "Argument[0]"] + - [mongodb.MongoClient, mongodb.AutoEncryptionOptions, "Member[keyVaultClient]"] + - [mongodb.MongoClient, mongodb.ChangeStream, "Member[parent]"] + - [mongodb.MongoClient, mongodb.DbStatic, "Argument[0]"] + - [mongodb.MongoClient, mongodb.MongoClient, "Member[connect].Argument[0].TypeVar[mongodb.Callback.0]"] + - [mongodb.MongoClient, mongodb.MongoClient, "Member[connect].WithArity[0].ReturnValue.Awaited"] + - [mongodb.MongoClient, mongodb.MongoClientEvents, "Member[open].Argument[0]"] + - [mongodb.MongoClient, mongodb.MongoClientStatic, Instance] + - [mongodb.MongoClient, mongodb.MongoClientStatic, "Member[connect].Argument[1,2].TypeVar[mongodb.Callback.0]"] + - [mongodb.MongoClient, mongodb.MongoClientStatic, "Member[connect].WithArity[1,2].ReturnValue.Awaited"] + - [mongodb.MongoClient, "mongodb/mongodb.MongoClient", ""] + - [mongodb.MongoClient, mongoose.mongodb.MongoClient, ""] + - [mongodb.MongoClientEvents, "mongodb/mongodb.MongoClientEvents", ""] + - [mongodb.MongoClientEvents, mongoose.mongodb.MongoClientEvents, ""] + - [mongodb.MongoClientOptions, mongodb.MongoClientStatic, "Argument[1]"] + - [mongodb.MongoClientOptions, mongodb.MongoClientStatic, "Member[connect].Argument[1]"] + - [mongodb.MongoClientOptions, "mongodb/mongodb.MongoClientOptions", ""] + - [mongodb.MongoClientOptions, mongoose.mongodb.MongoClientOptions, ""] + - [mongodb.MongoClientStatic, "mongodb/mongodb.MongoClientStatic", ""] + - [mongodb.MongoClientStatic, mongodb, "Member[MongoClient]"] + - [mongodb.MongoClientStatic, mongoose.mongodb.MongoClientStatic, ""] + - [mongodb.MongoOptions, mongodb.ClientSession, "Member[clientOptions]"] + - [mongodb.MongoOptions, mongodb.MongoClient, "Member[options]"] + - [mongodb.MongoOptions, "mongodb/mongodb.MongoOptions", ""] + - [mongodb.MongoOptions, mongoose.mongodb.MongoOptions, ""] + - [mongodb.OperationOptions, mongodb.Collection, "Member[isCapped,options].Argument[0]"] + - [mongodb.OperationOptions, mongodb.CommandOperationOptions, ""] + - [mongodb.OperationOptions, "mongodb/mongodb.OperationOptions", ""] + - [mongodb.OperationOptions, mongoose.mongodb.OperationOptions, ""] + - [mongodb.OrderedBulkOperation, mongodb.Collection, "Member[initializeOrderedBulkOp].ReturnValue"] + - [mongodb.OrderedBulkOperation, mongodb.OrderedBulkOperation, "Member[addToOperationsList].ReturnValue"] + - [mongodb.OrderedBulkOperation, mongodb.OrderedBulkOperationStatic, Instance] + - [mongodb.OrderedBulkOperation, "mongodb/mongodb.OrderedBulkOperation", ""] + - [mongodb.OrderedBulkOperation, mongoose.mongodb.OrderedBulkOperation, ""] + - [mongodb.OrderedBulkOperationStatic, "mongodb/mongodb.OrderedBulkOperationStatic", ""] + - [mongodb.OrderedBulkOperationStatic, mongodb, "Member[OrderedBulkOperation]"] + - [mongodb.OrderedBulkOperationStatic, mongoose.mongodb.OrderedBulkOperationStatic, ""] + - [mongodb.ProfilingLevelOptions, mongodb.Db, "Member[profilingLevel].Argument[0]"] + - [mongodb.ProfilingLevelOptions, "mongodb/mongodb.ProfilingLevelOptions", ""] + - [mongodb.ProfilingLevelOptions, mongoose.mongodb.ProfilingLevelOptions, ""] + - [mongodb.ReadPreferenceFromOptions, mongodb.ReadPreferenceStatic, "Member[fromOptions].Argument[0]"] + - [mongodb.ReadPreferenceFromOptions, "mongodb/mongodb.ReadPreferenceFromOptions", ""] + - [mongodb.ReadPreferenceFromOptions, mongoose.mongodb.ReadPreferenceFromOptions, ""] + - [mongodb.ReadPreferenceStatic, "mongodb/mongodb.ReadPreferenceStatic", ""] + - [mongodb.ReadPreferenceStatic, mongodb, "Member[ReadPreference]"] + - [mongodb.ReadPreferenceStatic, mongoose.mongodb.ReadPreferenceStatic, ""] + - [mongodb.RemoveUserOptions, mongodb.Admin, "Member[removeUser].Argument[1]"] + - [mongodb.RemoveUserOptions, mongodb.Db, "Member[removeUser].Argument[1]"] + - [mongodb.RemoveUserOptions, "mongodb/mongodb.RemoveUserOptions", ""] + - [mongodb.RemoveUserOptions, mongoose.mongodb.RemoveUserOptions, ""] + - [mongodb.RenameOptions, mongodb.Collection, "Member[rename].Argument[1]"] + - [mongodb.RenameOptions, mongodb.Db, "Member[renameCollection].Argument[2]"] + - [mongodb.RenameOptions, "mongodb/mongodb.RenameOptions", ""] + - [mongodb.RenameOptions, mongoose.mongodb.RenameOptions, ""] + - [mongodb.ReplaceOptions, mongodb.Collection, "Member[replaceOne].Argument[2]"] + - [mongodb.ReplaceOptions, "mongodb/mongodb.ReplaceOptions", ""] + - [mongodb.ReplaceOptions, mongoose.mongodb.ReplaceOptions, ""] + - [mongodb.RunCommandOptions, mongodb.Admin, "Member[command].Argument[1]"] + - [mongodb.RunCommandOptions, mongodb.Db, "Member[command].Argument[1]"] + - [mongodb.RunCommandOptions, "mongodb/mongodb.RunCommandOptions", ""] + - [mongodb.RunCommandOptions, mongoose.mongodb.RunCommandOptions, ""] + - [mongodb.SelectServerOptions, "mongodb/mongodb.SelectServerOptions", ""] + - [mongodb.SelectServerOptions, mongoose.mongodb.SelectServerOptions, ""] + - [mongodb.SetProfilingLevelOptions, mongodb.Db, "Member[setProfilingLevel].Argument[1]"] + - [mongodb.SetProfilingLevelOptions, "mongodb/mongodb.SetProfilingLevelOptions", ""] + - [mongodb.SetProfilingLevelOptions, mongoose.mongodb.SetProfilingLevelOptions, ""] + - [mongodb.Transaction, mongodb.ClientSession, "Member[transaction]"] + - [mongodb.Transaction, mongodb.TransactionStatic, Instance] + - [mongodb.Transaction, "mongodb/mongodb.Transaction", ""] + - [mongodb.Transaction, mongoose.mongodb.Transaction, ""] + - [mongodb.TransactionOptions, mongodb.ClientSession, "Member[defaultTransactionOptions]"] + - [mongodb.TransactionOptions, mongodb.ClientSession, "Member[startTransaction].Argument[0]"] + - [mongodb.TransactionOptions, mongodb.ClientSession, "Member[withTransaction].Argument[1]"] + - [mongodb.TransactionOptions, mongodb.ClientSessionOptions, "Member[defaultTransactionOptions]"] + - [mongodb.TransactionOptions, mongodb.Transaction, "Member[options]"] + - [mongodb.TransactionOptions, "mongodb/mongodb.TransactionOptions", ""] + - [mongodb.TransactionOptions, mongoose.mongodb.TransactionOptions, ""] + - [mongodb.TransactionStatic, "mongodb/mongodb.TransactionStatic", ""] + - [mongodb.TransactionStatic, mongodb, "Member[Transaction]"] + - [mongodb.TransactionStatic, mongoose.mongodb.TransactionStatic, ""] + - [mongodb.TypedEventEmitter, mongodb.AbstractCursor, ""] + - [mongodb.TypedEventEmitter, mongodb.ChangeStream, ""] + - [mongodb.TypedEventEmitter, mongodb.ClientSession, ""] + - [mongodb.TypedEventEmitter, mongodb.GridFSBucket, ""] + - [mongodb.TypedEventEmitter, mongodb.MongoClient, ""] + - [mongodb.UnorderedBulkOperation, mongodb.Collection, "Member[initializeUnorderedBulkOp].ReturnValue"] + - [mongodb.UnorderedBulkOperation, mongodb.UnorderedBulkOperation, "Member[addToOperationsList].ReturnValue"] + - [mongodb.UnorderedBulkOperation, mongodb.UnorderedBulkOperationStatic, Instance] + - [mongodb.UnorderedBulkOperation, "mongodb/mongodb.UnorderedBulkOperation", ""] + - [mongodb.UnorderedBulkOperation, mongoose.mongodb.UnorderedBulkOperation, ""] + - [mongodb.UnorderedBulkOperationStatic, "mongodb/mongodb.UnorderedBulkOperationStatic", ""] + - [mongodb.UnorderedBulkOperationStatic, mongodb, "Member[UnorderedBulkOperation]"] + - [mongodb.UnorderedBulkOperationStatic, mongoose.mongodb.UnorderedBulkOperationStatic, ""] + - [mongodb.UpdateManyModel, mongodb.AnyBulkWriteOperation, "Member[updateMany]"] + - [mongodb.UpdateManyModel, "mongodb/mongodb.UpdateManyModel", ""] + - [mongodb.UpdateManyModel, mongoose.mongodb.UpdateManyModel, ""] + - [mongodb.UpdateOneModel, mongodb.AnyBulkWriteOperation, "Member[updateOne]"] + - [mongodb.UpdateOneModel, "mongodb/mongodb.UpdateOneModel", ""] + - [mongodb.UpdateOneModel, mongoose.mongodb.UpdateOneModel, ""] + - [mongodb.UpdateOptions, mongodb.Collection, "Member[update,updateMany,updateOne].Argument[2]"] + - [mongodb.UpdateOptions, "mongodb/mongodb.UpdateOptions", ""] + - [mongodb.UpdateOptions, mongoose.mongodb.UpdateOptions, ""] + - [mongodb.ValidateCollectionOptions, mongodb.Admin, "Member[validateCollection].Argument[1]"] + - [mongodb.ValidateCollectionOptions, "mongodb/mongodb.ValidateCollectionOptions", ""] + - [mongodb.ValidateCollectionOptions, mongoose.mongodb.ValidateCollectionOptions, ""] + - [mongodb.WithSessionCallback, mongodb.MongoClient, "Member[withSession].Argument[1]"] + - [mongodb.WithSessionCallback, mongodb.MongoClient, "Member[withSession].WithArity[1].Argument[0]"] + - [mongodb.WithSessionCallback, "mongodb/mongodb.WithSessionCallback", ""] + - [mongodb.WithSessionCallback, mongoose.mongodb.WithSessionCallback, ""] + - [mongodb.WithTransactionCallback, mongodb.ClientSession, "Member[withTransaction].Argument[0]"] + - [mongodb.WithTransactionCallback, "mongodb/mongodb.WithTransactionCallback", ""] + - [mongodb.WithTransactionCallback, mongoose.mongodb.WithTransactionCallback, ""] + - [mongodb, mongoose, "Member[mongodb]"] + - [mongoose.AcceptsDiscriminator, mongoose.Model, ""] + - [mongoose.AcceptsDiscriminator, mongoose.Schema.Types.Array, ""] + - [mongoose.AcceptsDiscriminator, mongoose.Schema.Types.DocumentArray, ""] + - [mongoose.AcceptsDiscriminator, mongoose.Schema.Types.Subdocument, ""] + - [mongoose.Aggregate, mongoose.Aggregate, "Member[addCursorFlag,addFields,allowDiskUse,append,collation,count,facet,graphLookup,group,hint,limit,lookup,match,model,near,option,project,read,readConcern,redact,replaceRoot,sample,search,session,skip,sort,sortByCount,unionWith,unwind].ReturnValue"] + - [mongoose.Aggregate, mongoose.AggregateStatic, Instance] + - [mongoose.Aggregate, mongoose.Model, "Member[aggregate].ReturnValue"] + - [mongoose.AggregateStatic, mongoose, "Member[Aggregate]"] + - [mongoose.Collection, mongoose.Collection, Instance] + - [mongoose.Collection, mongoose.Connection, "Member[collection].ReturnValue"] + - [mongoose.Collection, mongoose.Connection, "Member[collections].AnyMember"] + - [mongoose.Collection, mongoose.Document, "Member[collection]"] + - [mongoose.Collection, mongoose.Model, "Member[collection]"] + - [mongoose.Collection, mongoose, "Member[Collection]"] + - [mongoose.CollectionBase, mongoose.Collection, ""] + - [mongoose.CompileModelOptions, mongoose.Connection, "Member[model].Argument[3]"] + - [mongoose.CompileModelOptions, mongoose, "Member[model].Argument[3]"] + - [mongoose.ConnectOptions, mongoose.Connection, "Member[openUri].WithArity[1,2,3].Argument[1]"] + - [mongoose.ConnectOptions, mongoose, "Member[connect,createConnection].WithArity[1,2,3].Argument[1]"] + - [mongoose.Connection, mongoose.Collection, "Argument[1]"] + - [mongoose.Connection, mongoose.CollectionBase, "Member[conn]"] + - [mongoose.Connection, mongoose.CompileModelOptions, "Member[connection]"] + - [mongoose.Connection, mongoose.Connection, "Member[asPromise].ReturnValue.Awaited"] + - [mongoose.Connection, mongoose.Connection, "Member[deleteModel,plugin,setClient,useDb].ReturnValue"] + - [mongoose.Connection, mongoose.Connection, "Member[openUri].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.Connection, mongoose.Connection, "Member[openUri].WithArity[1,2].ReturnValue.Awaited"] + - [mongoose.Connection, mongoose.Connection, "Member[openUri].WithArity[2,3].ReturnValue"] + - [mongoose.Connection, mongoose.Connection, "Member[openUri].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]"] + - [mongoose.Connection, mongoose.ConnectionStatic, Instance] + - [mongoose.Connection, mongoose.Document, "Member[db]"] + - [mongoose.Connection, mongoose.Model, "Member[db]"] + - [mongoose.Connection, mongoose, "Member[connection]"] + - [mongoose.Connection, mongoose, "Member[connections].ArrayElement"] + - [mongoose.Connection, mongoose, "Member[createConnection].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.Connection, mongoose, "Member[createConnection].WithArity[0,1,2].ReturnValue"] + - [mongoose.Connection, mongoose, "Member[createConnection].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]"] + - [mongoose.ConnectionStatic, mongoose, "Member[Connection]"] + - [mongoose.Cursor, mongoose.Query, "Member[cursor].ReturnValue"] + - [mongoose.DiscriminatorModel, mongoose.DiscriminatorSchema, "TypeVar[mongoose.Schema.1]"] + - [mongoose.Document, mongoose.Document, "Member[$getAllSubdocs,$getPopulatedDocs].ReturnValue.ArrayElement"] + - [mongoose.Document, mongoose.Document, "Member[$inc,$parent,$set,depopulate,increment,init,overwrite,set].ReturnValue"] + - [mongoose.Document, mongoose.Document, "Member[delete,deleteOne].WithArity[0,1].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]"] + - [mongoose.Document, mongoose.Document, "Member[equals].Argument[0]"] + - [mongoose.Document, mongoose.Document, "Member[init].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.Document, mongoose.Document, "Member[remove,save].WithArity[0,1].ReturnValue.Awaited"] + - [mongoose.Document, mongoose.Document, "Member[replaceOne,update,updateOne].ReturnValue.TypeVar[mongoose.Query.1]"] + - [mongoose.Document, mongoose.Document, "Member[save].Argument[1].TypeVar[mongoose.Callback.0]"] + - [mongoose.Document, mongoose.Document, "Member[save].WithArity[1].Argument[0].TypeVar[mongoose.Callback.0]"] + - [mongoose.Document, mongoose.DocumentStatic, Instance] + - [mongoose.Document, mongoose.Error.VersionErrorStatic, "Argument[0]"] + - [mongoose.Document, mongoose.HydratedDocument, ""] + - [mongoose.Document, mongoose.HydratedDocument, "TypeVar[mongoose.Require_id.0]"] + - [mongoose.Document, mongoose.Model, "Member[bulkSave].Argument[0].ArrayElement"] + - [mongoose.Document, mongoose.TVirtualPathFN, "Argument[2]"] + - [mongoose.Document, mongoose.Types.Subdocument, ""] + - [mongoose.Document, mongoose.Types.Subdocument, "Member[$parent,ownerDocument,parent].ReturnValue"] + - [mongoose.Document, mongoose.VirtualType, "Member[applyGetters,applySetters].Argument[1]"] + - [mongoose.DocumentStatic, mongoose, "Member[Document]"] + - [mongoose.Error.VersionErrorStatic, mongoose, "Member[Error].Member[VersionError]"] + - [mongoose.HydratedDocument, mongoose.Model, Instance] + - [mongoose.HydratedDocument, mongoose.Model, "Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,geoSearch,remove,replaceOne,update,updateMany,updateOne,where].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[$where,find,geoSearch,where].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[create,insertMany].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[create].WithArity[0..,1,2].ReturnValue.Awaited.ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[create].WithArity[1].ReturnValue.Awaited"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[create].WithArity[2].Argument[1].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[exists].WithArity[1,2].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[find,insertMany].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findById,findOne].Argument[3].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findByIdAndDelete,findByIdAndRemove,findOneAndDelete,findOneAndRemove].Argument[2].Argument[1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.ModifyResult.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findByIdAndUpdate].WithArity[0,1,2,4].Argument[3].Argument[1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findByIdAndUpdate].WithArity[3].Argument[2,3].Argument[1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findById].WithArity[1,2,3].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findOneAndReplace].WithArity[0,1,2,3,4].Argument[3].Argument[1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findOneAndUpdate].WithArity[3,4].Argument[3].Argument[1]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findOne].WithArity[0,1,2].Argument[1,2].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[findOne].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[find].Argument[3].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[find].WithArity[0].Argument[0].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[find].WithArity[1].Argument[0,1,2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[find].WithArity[2].Argument[1,2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[geoSearch].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[hydrate].ReturnValue"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[init].ReturnValue.Awaited"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[insertMany].WithArity[1,2].ReturnValue.Awaited.ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[populate].WithArity[2,3].Argument[2].TypeVar[mongoose.Callback.0]"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[populate].WithArity[2,3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[populate].WithArity[2,3].ReturnValue.Awaited"] + - [mongoose.HydratedDocument, mongoose.Model, "Member[populate].WithArity[2,3].ReturnValue.Awaited.ArrayElement"] + - [mongoose.HydratedDocument, mongoose.TVirtualPathFN, "Argument[1].TypeVar[mongoose.VirtualType.0]"] + - [mongoose.HydratedDocument, mongoose.VirtualPathFunctions, "Member[options].TypeVar[mongoose.VirtualTypeOptions.0]"] + - [mongoose.InsertManyOptions, mongoose.Model, "Member[insertMany].WithArity[2,3].Argument[1]"] + - [mongoose.Model, mongoose.AcceptsDiscriminator, "Member[discriminator].WithArity[2,3].ReturnValue"] + - [mongoose.Model, mongoose.Aggregate, "Member[model].Argument[0]"] + - [mongoose.Model, mongoose.Connection, "Member[model].WithArity[1,2,3,4].ReturnValue"] + - [mongoose.Model, mongoose.Connection, "Member[models].AnyMember"] + - [mongoose.Model, mongoose.DiscriminatorModel, ""] + - [mongoose.Model, mongoose.Document, "Member[$model].ReturnValue"] + - [mongoose.Model, mongoose.Document, "Member[populate].Argument[2]"] + - [mongoose.Model, mongoose.Model, "Member[discriminators].AnyMember"] + - [mongoose.Model, mongoose.Models, AnyMember] + - [mongoose.Model, mongoose.PopulateOptions, "Member[model]"] + - [mongoose.Model, mongoose.Query, "Member[cast].Argument[0]"] + - [mongoose.Model, mongoose.Query, "Member[populate].Argument[2]"] + - [mongoose.Model, mongoose.Schema.Types.Array, "Member[discriminator].WithArity[2,3].ReturnValue"] + - [mongoose.Model, mongoose.Schema.Types.DocumentArray, "Member[discriminator].WithArity[2,3].ReturnValue"] + - [mongoose.Model, mongoose.Schema.Types.Subdocument, "Member[discriminator].WithArity[2,3].ReturnValue"] + - [mongoose.Model, mongoose.SchemaStatic, "Instance.TypeVar[mongoose.Schema.1]"] + - [mongoose.Model, mongoose, "Member[Model]"] + - [mongoose.Model, mongoose, "Member[model].ReturnValue"] + - [mongoose.Models, mongoose, "Member[models]"] + - [mongoose.PopulateOption, mongoose.InsertManyOptions, ""] + - [mongoose.PopulateOption, mongoose.QueryOptions, ""] + - [mongoose.PopulateOptions, mongoose.Document, "Member[populate].Argument[4]"] + - [mongoose.PopulateOptions, mongoose.Document, "Member[populate].WithArity[1,2].Argument[0]"] + - [mongoose.PopulateOptions, mongoose.Document, "Member[populate].WithArity[1,2].Argument[0].ArrayElement"] + - [mongoose.PopulateOptions, mongoose.Model, "Member[populate].Argument[1]"] + - [mongoose.PopulateOptions, mongoose.Model, "Member[populate].Argument[1].ArrayElement"] + - [mongoose.PopulateOptions, mongoose.PopulateOption, "Member[populate]"] + - [mongoose.PopulateOptions, mongoose.PopulateOption, "Member[populate].ArrayElement"] + - [mongoose.PopulateOptions, mongoose.PopulateOptions, "Member[populate]"] + - [mongoose.PopulateOptions, mongoose.PopulateOptions, "Member[populate].ArrayElement"] + - [mongoose.PopulateOptions, mongoose.Query, "Member[populate].WithArity[1].Argument[0]"] + - [mongoose.PopulateOptions, mongoose.Query, "Member[populate].WithArity[1].Argument[0].ArrayElement"] + - [mongoose.Query, mongoose.Document, "Member[replaceOne,update,updateOne].ReturnValue"] + - [mongoose.Query, mongoose.HydratedDocument, "TypeVar[mongoose.Require_id.0]"] + - [mongoose.Query, mongoose.Query, "Member[all,allowDiskUse,and,batchSize,box,circle,clone,collation,comment,elemMatch,equals,exists,explain,geometry,gt,gte,hint,in,intersects,j,limit,lt,lte,maxDistance,maxScan,maxTimeMS,merge,mod,ne,near,nin,nor,or,polygon,read,readConcern,regex,remove,select,session,set,setOptions,size,skip,slice,snapshot,sort,tailable,w,where,within,wtimeout].ReturnValue"] + - [mongoose.Query, mongoose.Query, "Member[error].WithArity[1].ReturnValue"] + - [mongoose.Query, mongoose.Query, "Member[merge].Argument[0]"] + - [mongoose.Query, mongoose.QueryStatic, Instance] + - [mongoose.Query, mongoose.QueryWithHelpers, ""] + - [mongoose.QueryOptions, mongoose.Document, "Member[delete,deleteOne,remove].WithArity[0,1,2].Argument[0]"] + - [mongoose.QueryOptions, mongoose.Document, "Member[replaceOne,update,updateOne].Argument[1]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[countDocuments,findByIdAndDelete,findByIdAndRemove,findOneAndDelete,findOneAndRemove].Argument[1]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[estimatedDocumentCount].Argument[0]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[find,findById].WithArity[1,2,3,4].Argument[2]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[findByIdAndUpdate,findOne,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2]"] + - [mongoose.QueryOptions, mongoose.Model, "Member[replaceOne,update,updateMany,updateOne].Argument[2]"] + - [mongoose.QueryOptions, mongoose.PopulateOptions, "Member[options]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[countDocuments,findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[1]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[cursor,estimatedDocumentCount,setOptions].Argument[0]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.1]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[findByIdAndUpdate,findOne,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[find].WithArity[1,2,3,4].Argument[2]"] + - [mongoose.QueryOptions, mongoose.Query, "Member[getOptions].ReturnValue"] + - [mongoose.QueryOptions, mongoose.Query, "Member[replaceOne,update,updateMany,updateOne].Argument[2]"] + - [mongoose.QueryOptions, mongoose.VirtualTypeOptions, "Member[options]"] + - [mongoose.QueryStatic, mongoose, "Member[Query]"] + - [mongoose.QueryWithHelpers, mongoose.Document, "Member[delete,deleteOne].WithArity[0,1].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Model, "Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,findById,findByIdAndDelete,findByIdAndRemove,findOne,findOneAndDelete,findOneAndRemove,geoSearch,remove,replaceOne,update,updateMany,updateOne,where].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Model, "Member[exists].WithArity[1,2].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Model, "Member[findByIdAndUpdate,findOneAndReplace,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Query, "Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove,lean,orFail,populate,replaceOne,transform,update,updateMany,updateOne].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Query, "Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue"] + - [mongoose.QueryWithHelpers, mongoose.Query, "Member[toConstructor].ReturnValue.Instance"] + - [mongoose.Schema.Types.Array, mongoose.Schema.Types.Array, "Member[enum].ReturnValue"] + - [mongoose.Schema.Types.Array, mongoose.Schema.Types.ArrayStatic, Instance] + - [mongoose.Schema.Types.ArrayStatic, mongoose, "Member[Schema].Member[Types].Member[Array]"] + - [mongoose.Schema.Types.DocumentArray, mongoose.Schema.Types.DocumentArrayStatic, Instance] + - [mongoose.Schema.Types.DocumentArrayStatic, mongoose, "Member[Schema].Member[Types].Member[DocumentArray]"] + - [mongoose.Schema.Types.Subdocument, mongoose.Schema.Types.SubdocumentStatic, Instance] + - [mongoose.Schema.Types.SubdocumentStatic, mongoose.Schema.Types.DocumentArray, "Member[caster]"] + - [mongoose.Schema.Types.SubdocumentStatic, mongoose, "Member[Schema].Member[Types].Member[Subdocument]"] + - [mongoose.SchemaStatic, mongoose, "Member[Schema]"] + - [mongoose.SessionOperation, mongoose.Aggregate, ""] + - [mongoose.SessionOperation, mongoose.Query, ""] + - [mongoose.TVirtualPathFN, mongoose.VirtualPathFunctions, "Member[get,set]"] + - [mongoose.Types.Array, mongoose.Types.DocumentArray, ""] + - [mongoose.Types.ArraySubdocument, mongoose.Types.ArraySubdocumentStatic, Instance] + - [mongoose.Types.ArraySubdocumentStatic, mongoose, "Member[Types].Member[ArraySubdocument]"] + - [mongoose.Types.DocumentArray, mongoose.Types.ArraySubdocument, "Member[parentArray].ReturnValue"] + - [mongoose.Types.DocumentArray, mongoose.Types.DocumentArrayStatic, Instance] + - [mongoose.Types.DocumentArray, "mongoose/inferschematype.ResolvePathType", "TypeVar[mongoose.IfEquals.3]"] + - [mongoose.Types.DocumentArrayStatic, mongoose, "Member[Types].Member[DocumentArray]"] + - [mongoose.Types.ObjectId, "mongoose/inferschematype.ResolvePathType", ""] + - [mongoose.Types.Subdocument, mongoose.Types.ArraySubdocument, ""] + - [mongoose.Types.Subdocument, mongoose.Types.DocumentArray, "Member[create,id].ReturnValue"] + - [mongoose.Types.Subdocument, mongoose.Types.DocumentArray, "TypeVar[mongoose.Types.Array.0]"] + - [mongoose.Types.Subdocument, mongoose.Types.SubdocumentStatic, Instance] + - [mongoose.Types.SubdocumentStatic, mongoose, "Member[Types].Member[Subdocument]"] + - [mongoose.VirtualType, mongoose.TVirtualPathFN, "Argument[1]"] + - [mongoose.VirtualType, mongoose.VirtualType, "Member[get,set].Argument[0].Argument[1]"] + - [mongoose.VirtualType, mongoose.VirtualType, "Member[get,set].ReturnValue"] + - [mongoose.VirtualType, mongoose.VirtualTypeStatic, Instance] + - [mongoose.VirtualTypeOptions, mongoose.VirtualPathFunctions, "Member[options]"] + - [mongoose.VirtualTypeStatic, mongoose, "Member[VirtualType]"] + - ["mongoose/inferschematype.ResolvePathType", "mongoose/inferschematype.ObtainDocumentPathType", ""] + - ["mongoose/inferschematype.ResolvePathType", "mongoose/inferschematype.ResolvePathType", "TypeVar[mongoose.IfEquals.3].ArrayElement"] + - ["mongoose/inferschematype.ResolvePathType", "mongoose/inferschematype.ResolvePathType", "TypeVar[mongoose.IfEquals.3].TypeVar[mongoose.Types.DocumentArray.0]"] + - [mongoose, mongoose, "Member[mongoose]"] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [mongodb.AbstractCursor, "", "", "Member[addCursorFlag,batchSize,maxTimeMS,withReadConcern,withReadPreference].ReturnValue", type] + - [mongodb.BulkOperationBase, "", "", "Member[addToOperationsList,raw].ReturnValue", type] + - [mongodb.FindCursor, "", "", "Member[addQueryModifier,allowDiskUse,collation,comment,filter,hint,limit,max,maxAwaitTimeMS,maxTimeMS,min,returnKey,showRecordId,skip,sort].ReturnValue", type] + - [mongodb.FindOperators, "", "", "Member[arrayFilters,collation,upsert].ReturnValue", type] + - [mongodb.GridFSBucketWriteStream, "", "", "Member[end].ReturnValue", type] + - [mongodb.MongoClient, "", "", "Member[connect].Argument[0].TypeVar[mongodb.Callback.0]", type] + - [mongodb.MongoClient, "", "", "Member[connect].WithArity[0].ReturnValue.Awaited", type] + - [mongodb.OrderedBulkOperation, "", "", "Member[addToOperationsList].ReturnValue", type] + - [mongodb.TypedEventEmitter, "", "", "Member[addListener,off,on,once,prependListener,prependOnceListener,removeAllListeners,removeListener,setMaxListeners].ReturnValue", type] + - [mongodb.UnorderedBulkOperation, "", "", "Member[addToOperationsList].ReturnValue", type] + - [mongoose.Aggregate, "", "", "Member[addCursorFlag,addFields,allowDiskUse,append,collation,count,facet,graphLookup,group,hint,limit,lookup,match,model,near,option,project,read,readConcern,redact,replaceRoot,sample,search,session,skip,sort,sortByCount,unionWith,unwind].ReturnValue", type] + - [mongoose.Connection, "", "", "Member[asPromise].ReturnValue.Awaited", type] + - [mongoose.Connection, "", "", "Member[deleteModel,setClient].ReturnValue", type] + - [mongoose.Cursor, "", "", "Member[addCursorFlag].ReturnValue", type] + - [mongoose.Document, "", "", "Member[$inc,$set,depopulate,increment,init,overwrite,set].ReturnValue", type] + - [mongoose.Document, "", "", "Member[delete,deleteOne].WithArity[0,1].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]", type] + - [mongoose.Document, "", "", "Member[getChanges].ReturnValue.TypeVar[mongoose.UpdateQuery.0]", type] + - [mongoose.Document, "", "", "Member[init].Argument[2].TypeVar[mongoose.Callback.0]", type] + - [mongoose.Document, "", "", "Member[populate].Argument[1,5].TypeVar[mongoose.Callback.0].TypeVar[mongoose.MergeType.0]", type] + - [mongoose.Document, "", "", "Member[populate].WithArity[1,2,3,4,5].ReturnValue.Awaited.TypeVar[mongoose.MergeType.0]", type] + - [mongoose.Document, "", "", "Member[remove,save].WithArity[0,1].ReturnValue.Awaited", type] + - [mongoose.Document, "", "", "Member[replaceOne,update,updateOne].ReturnValue.TypeVar[mongoose.Query.1]", type] + - [mongoose.Document, "", "", "Member[save].Argument[1].TypeVar[mongoose.Callback.0]", type] + - [mongoose.Document, "", "", "Member[save].WithArity[1].Argument[0].TypeVar[mongoose.Callback.0]", type] + - [mongoose.Document, "", "", "Member[update,updateOne].Argument[0].TypeVar[mongoose.UpdateQuery.0]", type] + - [mongoose.Query, "", "", "Member[all,allowDiskUse,and,batchSize,box,circle,clone,collation,comment,elemMatch,equals,exists,explain,geometry,gt,gte,hint,in,intersects,j,limit,lt,lte,maxDistance,maxScan,maxTimeMS,merge,mod,ne,near,nin,nor,or,polygon,read,readConcern,regex,select,session,set,setOptions,size,skip,slice,snapshot,sort,tailable,w,where,within,wtimeout].ReturnValue", type] + - [mongoose.Query, "", "", "Member[error].WithArity[1].ReturnValue", type] + - [mongoose.Schema.Types.Array, "", "", "Member[enum].ReturnValue", type] + - [mongoose.SessionOperation, "", "", "Member[session].ReturnValue", type] + - [mongoose.Types.Array, "", "", "Member[pull,remove,set].ReturnValue", type] + - [mongoose.Types.ObjectId, "", "", "Member[_id]", type] + - [mongoose.VirtualType, "", "", "Member[get,set].ReturnValue", type] + + - addsTo: + pack: codeql/javascript-all + extensible: typeVariableModel + data: + - [mongodb.Callback.0, "Argument[1]"] + - [mongoose.Callback.0, "Argument[1]"] + - [mongoose.Cursor.0, "Member[eachAsync].WithArity[1,2,3].Argument[0].Argument[0]"] + - [mongoose.Cursor.0, "Member[eachAsync].WithArity[2,3].Argument[0].Argument[0].ArrayElement"] + - [mongoose.Cursor.0, "Member[map].Argument[0].Argument[0]"] + - [mongoose.Cursor.0, "Member[next].Argument[0].TypeVar[mongoose.Callback.0]"] + - [mongoose.Cursor.0, "Member[next].WithArity[0].ReturnValue.Awaited"] + - [mongoose.Cursor.1, "Member[map].ReturnValue.TypeVar[mongoose.Cursor.1]"] + - [mongoose.Cursor.1, "Member[options]"] + - [mongoose.DiscriminatorSchema.1, "TypeVar[mongoose.Schema.1]"] + - [mongoose.DiscriminatorSchema.1, "TypeVar[mongoose.Schema.1].TypeVar[mongoose.DiscriminatorModel.1]"] + - [mongoose.Document.0, "Member[_id]"] + - [mongoose.Document.0, "Member[equals].Argument[0].TypeVar[mongoose.Document.0]"] + - [mongoose.FilterQuery.0, "TypeVar[mongoose._FilterQuery.0]"] + - [mongoose.IfAny.1, ""] + - [mongoose.IfAny.2, ""] + - [mongoose.IfEquals.3, ""] + - [mongoose.LeanDocumentOrArray.0, ""] + - [mongoose.LeanDocumentOrArray.0, "TypeVar[mongoose.LeanDocument.0]"] + - [mongoose.LeanDocumentOrArrayWithRawType.0, ""] + - [mongoose.ModifyResult.0, "Member[value].TypeVar[mongoose.Require_id.0]"] + - [mongoose.PluginFunction.1, "Argument[0].TypeVar[mongoose.Schema.1]"] + - [mongoose.PostMiddlewareFunction.1, "Argument[0]"] + - [mongoose.Query.0, "Member[exec].Argument[0].TypeVar[mongoose.Callback.0]"] + - [mongoose.Query.0, "Member[exec].WithArity[0].ReturnValue.Awaited"] + - [mongoose.Query.0, "Member[lean].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.LeanDocumentOrArray.0,mongoose.LeanDocumentOrArrayWithRawType.0]"] + - [mongoose.Query.0, "Member[orFail].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0]"] + - [mongoose.Query.0, "Member[populate].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.UnpackedIntersection.0]"] + - [mongoose.Query.0, "Member[then,transform].Argument[0].Argument[0]"] + - [mongoose.Query.0, "Member[toConstructor].ReturnValue.Instance.TypeVar[mongoose.QueryWithHelpers.0]"] + - [mongoose.Query.1, "Member[$where,count,countDocuments,deleteMany,deleteOne,distinct,estimatedDocumentCount,find,lean,orFail,populate,replaceOne,transform,update,updateMany,updateOne].ReturnValue.TypeVar[mongoose.QueryWithHelpers.1]"] + - [mongoose.Query.1, "Member[$where,find].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].ArrayElement"] + - [mongoose.Query.1, "Member[_mongooseOptions].TypeVar[mongoose.MongooseQueryOptions.0]"] + - [mongoose.Query.1, "Member[and,nor,or].Argument[0].ArrayElement.TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[countDocuments,findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[1].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[countDocuments].WithArity[1,2,3].Argument[0].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[count].WithArity[1,2].Argument[0].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[cursor,estimatedDocumentCount,setOptions].Argument[0].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.0]"] + - [mongoose.Query.1, "Member[cursor].ReturnValue.TypeVar[mongoose.Cursor.1].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[0].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[deleteMany,deleteOne].WithArity[0,1,2,3].Argument[1].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[distinct].Argument[1].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[findByIdAndDelete,findOne,findOneAndDelete,findOneAndRemove].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]"] + - [mongoose.Query.1, "Member[findByIdAndDelete,findOneAndDelete,findOneAndRemove].Argument[2].Argument[1]"] + - [mongoose.Query.1, "Member[findByIdAndUpdate,findOneAndUpdate,update,updateMany,updateOne].Argument[1].TypeVar[mongoose.UpdateQuery.0]"] + - [mongoose.Query.1, "Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].Argument[2].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[findByIdAndUpdate,findOneAndUpdate].WithArity[0,1,2,3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0,mongoose.QueryWithHelpers.1]"] + - [mongoose.Query.1, "Member[findByIdAndUpdate].WithArity[0,1,2,4].Argument[3].Argument[1]"] + - [mongoose.Query.1, "Member[findByIdAndUpdate].WithArity[3].Argument[2,3].Argument[1]"] + - [mongoose.Query.1, "Member[findOne,findOneAndDelete,findOneAndRemove,findOneAndUpdate,merge,remove,replaceOne,setQuery,update,updateMany,updateOne].Argument[0].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[findOneAndUpdate].Argument[3].Argument[1]"] + - [mongoose.Query.1, "Member[findOneAndUpdate].Argument[3].Argument[2].TypeVar[mongoose.ModifyResult.0]"] + - [mongoose.Query.1, "Member[findOneAndUpdate].WithArity[3,4].ReturnValue.TypeVar[mongoose.QueryWithHelpers.0].TypeVar[mongoose.ModifyResult.0]"] + - [mongoose.Query.1, "Member[findOne].Argument[3].TypeVar[mongoose.Callback.0]"] + - [mongoose.Query.1, "Member[findOne].WithArity[0,1,2,3].Argument[2].TypeVar[mongoose.Callback.0,mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[findOne].WithArity[0,1,2].Argument[1].TypeVar[mongoose.Callback.0,mongoose.ProjectionType.0]"] + - [mongoose.Query.1, "Member[findOne].WithArity[3,4].Argument[1].TypeVar[mongoose.ProjectionType.0]"] + - [mongoose.Query.1, "Member[findOne].WithArity[4].Argument[2].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[find].Argument[3].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.Query.1, "Member[find].WithArity[0].Argument[0].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.Query.1, "Member[find].WithArity[1,2,3,4].Argument[0].TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[find].WithArity[1,2,3,4].Argument[1].TypeVar[mongoose.ProjectionType.0]"] + - [mongoose.Query.1, "Member[find].WithArity[1,2,3,4].Argument[2].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[find].WithArity[1].Argument[0,1,2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.Query.1, "Member[find].WithArity[2].Argument[1,2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.Query.1, "Member[find].WithArity[3].Argument[2].TypeVar[mongoose.Callback.0].ArrayElement"] + - [mongoose.Query.1, "Member[getFilter,getQuery].ReturnValue.TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Query.1, "Member[getOptions].ReturnValue.TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[getUpdate].ReturnValue.TypeVar[mongoose.UpdateQuery.0]"] + - [mongoose.Query.1, "Member[projection].WithArity[0,1].Argument[0].TypeVar[mongoose.ProjectionFields.0]"] + - [mongoose.Query.1, "Member[projection].WithArity[0,1].ReturnValue.TypeVar[mongoose.ProjectionFields.0]"] + - [mongoose.Query.1, "Member[remove].ReturnValue.TypeVar[mongoose.Query.1]"] + - [mongoose.Query.1, "Member[replaceOne,update,updateMany,updateOne].Argument[2].TypeVar[mongoose.QueryOptions.0]"] + - [mongoose.Query.1, "Member[replaceOne].Argument[1]"] + - [mongoose.Query.1, "Member[setUpdate].Argument[0].TypeVar[mongoose.UpdateQuery.0]"] + - [mongoose.Query.1, "Member[toConstructor].ReturnValue.Instance.TypeVar[mongoose.QueryWithHelpers.1]"] + - [mongoose.QueryOptions.0, "Member[projection].TypeVar[mongoose.ProjectionType.0]"] + - [mongoose.QueryWithHelpers.0, "TypeVar[mongoose.Query.0]"] + - [mongoose.QueryWithHelpers.1, "TypeVar[mongoose.Query.1]"] + - [mongoose.Require_id.0, ""] + - [mongoose.Require_id.0, "TypeVar[mongoose.IfAny.1,mongoose.IfAny.2]"] + - [mongoose.RootQuerySelector.0, "Member[$and,$nor,$or].ArrayElement.TypeVar[mongoose.FilterQuery.0]"] + - [mongoose.Schema.1, "Member[discriminator].ReturnValue.TypeVar[mongoose.DiscriminatorSchema.1]"] + - [mongoose.Schema.1, "Member[plugin].Argument[0].TypeVar[mongoose.PluginFunction.1]"] + - [mongoose.Schema.1, "Member[post].Argument[2].TypeVar[mongoose.ErrorHandlingMiddlewareFunction.0,mongoose.PostMiddlewareFunction.0,mongoose.PostMiddlewareFunction.1]"] + - [mongoose.Schema.1, "Member[post].WithArity[2].WithStringArgument[0=insertMany].Argument[1].TypeVar[mongoose.ErrorHandlingMiddlewareFunction.0,mongoose.PostMiddlewareFunction.0,mongoose.PostMiddlewareFunction.1]"] + - [mongoose.Types.Array.0, "Member[$pop,$shift,shift].ReturnValue"] + - [mongoose.Types.Array.0, "Member[set].Argument[1]"] + - [mongoose.Types.DocumentArray.0, "Member[create,id].ReturnValue"] + - [mongoose.Types.DocumentArray.0, "Member[create,id].ReturnValue.TypeVar[mongoose.Types.Subdocument.0].TypeVar[mongoose.InferId.0]"] + - [mongoose.Types.DocumentArray.0, "Member[push].Argument[0].ArrayElement.TypeVar[mongoose.AnyKeys.0]"] + - [mongoose.Types.DocumentArray.0, "TypeVar[mongoose.Types.Array.0]"] + - [mongoose.Types.DocumentArray.0, "TypeVar[mongoose.Types.Array.0].TypeVar[mongoose.Types.Subdocument.0].TypeVar[mongoose.InferId.0]"] + - [mongoose.Types.Subdocument.0, "TypeVar[mongoose.Document.0]"] + - [mongoose.UnpackedIntersection.0, ""] + - [mongoose.UpdateQuery.0, "TypeVar[mongoose._UpdateQuery.0].TypeVar[mongoose._UpdateQueryDef.0]"] + - [mongoose.VirtualType.0, "Member[get,set].Argument[0].Argument[1].TypeVar[mongoose.VirtualType.0]"] + - [mongoose.VirtualType.0, "Member[get,set].Argument[0].Argument[2]"] + - [mongoose.VirtualTypeOptions.0, "Member[foreignField,localField].Argument[0]"] + - [mongoose._FilterQuery.0, "TypeVar[mongoose.RootQuerySelector.0]"] + - [mongoose._UpdateQuery.0, "Member[$currentDate,$inc,$max,$min,$mul,$pop,$pull,$pullAll,$push,$set,$setOnInsert,$unset].TypeVar[mongoose.AnyKeys.0]"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mssql/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/mssql/Model.qll deleted file mode 100644 index 7d119ebfc02..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/mssql/Model.qll +++ /dev/null @@ -1,45 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "mssql.ConnectionPool;mssql.ConnectionPool;Member[connect].WithArity[0].ReturnValue.Awaited", // - "mssql.ConnectionPool;mssql.ConnectionPoolStatic;Instance", // - "mssql.ConnectionPool;mssql/msnodesqlv8;Member[connect].ReturnValue.Awaited", // - "mssql.ConnectionPool;mssql/msnodesqlv8;Member[pool]", // - "mssql.ConnectionPool;mssql;Member[connect].ReturnValue.Awaited", // - "mssql.ConnectionPool;mssql;Member[pool]", // - "mssql.ConnectionPoolStatic;mssql/msnodesqlv8;Member[ConnectionPool]", // - "mssql.ConnectionPoolStatic;mssql;Member[ConnectionPool]", // - "mssql.PreparedStatement;mssql.PreparedStatement;Member[input,output].ReturnValue", // - "mssql.PreparedStatement;mssql.PreparedStatement;Member[prepare].WithArity[0,1,2].ReturnValue", // - "mssql.PreparedStatement;mssql.PreparedStatement;Member[unprepare].WithArity[1].ReturnValue", // - "mssql.PreparedStatement;mssql.PreparedStatementStatic;Instance", // - "mssql.PreparedStatement;mssql.Request;Member[pstatement]", // - "mssql.PreparedStatementStatic;mssql/msnodesqlv8;Member[PreparedStatement]", // - "mssql.PreparedStatementStatic;mssql;Member[PreparedStatement]", // - "mssql.Request;mssql.ConnectionPool;Member[request].ReturnValue", // - "mssql.Request;mssql.PreparedStatement;Member[execute].WithArity[2].ReturnValue", // - "mssql.Request;mssql.Request;Member[input,output,replaceInput].ReturnValue", // - "mssql.Request;mssql.Request;Member[replaceOutput].ReturnValue", // - "mssql.Request;mssql.RequestStatic;Instance", // - "mssql.Request;mssql.Transaction;Member[request].ReturnValue", // - "mssql.RequestStatic;mssql/msnodesqlv8;Member[Request]", // - "mssql.RequestStatic;mssql;Member[Request]", // - "mssql.Transaction;mssql.ConnectionPool;Member[transaction].ReturnValue", // - "mssql.Transaction;mssql.PreparedStatement;Member[transaction]", // - "mssql.Transaction;mssql.Request;Member[transaction]", // - "mssql.Transaction;mssql.Transaction;Member[begin].WithArity[0,1,2].ReturnValue", // - "mssql.Transaction;mssql.Transaction;Member[begin].WithArity[0,1].ReturnValue.Awaited", // - "mssql.Transaction;mssql.TransactionStatic;Instance", // - "mssql.TransactionStatic;mssql/msnodesqlv8;Member[Transaction]", // - "mssql.TransactionStatic;mssql;Member[Transaction]", // - "mssql.config;mssql.ConnectionPoolStatic;WithArity[1,2].Argument[0]", // - "mssql.config;mssql/msnodesqlv8;Member[connect].Argument[0]", // - "mssql.config;mssql;Member[connect].Argument[0]", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mssql/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/mssql/model.yml new file mode 100644 index 00000000000..bbc3279b81d --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/mssql/model.yml @@ -0,0 +1,39 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [mssql.ConnectionPool, mssql.ConnectionPool, "Member[connect].WithArity[0].ReturnValue.Awaited"] + - [mssql.ConnectionPool, mssql.ConnectionPoolStatic, Instance] + - [mssql.ConnectionPool, "mssql/msnodesqlv8", "Member[connect].ReturnValue.Awaited"] + - [mssql.ConnectionPool, "mssql/msnodesqlv8", "Member[pool]"] + - [mssql.ConnectionPool, mssql, "Member[connect].ReturnValue.Awaited"] + - [mssql.ConnectionPool, mssql, "Member[pool]"] + - [mssql.ConnectionPoolStatic, "mssql/msnodesqlv8", "Member[ConnectionPool]"] + - [mssql.ConnectionPoolStatic, mssql, "Member[ConnectionPool]"] + - [mssql.PreparedStatement, mssql.PreparedStatement, "Member[input,output].ReturnValue"] + - [mssql.PreparedStatement, mssql.PreparedStatement, "Member[prepare].WithArity[0,1,2].ReturnValue"] + - [mssql.PreparedStatement, mssql.PreparedStatement, "Member[unprepare].WithArity[1].ReturnValue"] + - [mssql.PreparedStatement, mssql.PreparedStatementStatic, Instance] + - [mssql.PreparedStatement, mssql.Request, "Member[pstatement]"] + - [mssql.PreparedStatementStatic, "mssql/msnodesqlv8", "Member[PreparedStatement]"] + - [mssql.PreparedStatementStatic, mssql, "Member[PreparedStatement]"] + - [mssql.Request, mssql.ConnectionPool, "Member[request].ReturnValue"] + - [mssql.Request, mssql.PreparedStatement, "Member[execute].WithArity[2].ReturnValue"] + - [mssql.Request, mssql.Request, "Member[input,output,replaceInput].ReturnValue"] + - [mssql.Request, mssql.Request, "Member[replaceOutput].ReturnValue"] + - [mssql.Request, mssql.RequestStatic, Instance] + - [mssql.Request, mssql.Transaction, "Member[request].ReturnValue"] + - [mssql.RequestStatic, "mssql/msnodesqlv8", "Member[Request]"] + - [mssql.RequestStatic, mssql, "Member[Request]"] + - [mssql.Transaction, mssql.ConnectionPool, "Member[transaction].ReturnValue"] + - [mssql.Transaction, mssql.PreparedStatement, "Member[transaction]"] + - [mssql.Transaction, mssql.Request, "Member[transaction]"] + - [mssql.Transaction, mssql.Transaction, "Member[begin].WithArity[0,1,2].ReturnValue"] + - [mssql.Transaction, mssql.Transaction, "Member[begin].WithArity[0,1].ReturnValue.Awaited"] + - [mssql.Transaction, mssql.TransactionStatic, Instance] + - [mssql.TransactionStatic, "mssql/msnodesqlv8", "Member[Transaction]"] + - [mssql.TransactionStatic, mssql, "Member[Transaction]"] + - [mssql.config, mssql.ConnectionPoolStatic, "WithArity[1,2].Argument[0]"] + - [mssql.config, "mssql/msnodesqlv8", "Member[connect].Argument[0]"] + - [mssql.config, mssql, "Member[connect].Argument[0]"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mysql/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/mysql/Model.qll deleted file mode 100644 index 34ea14abb0b..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/mysql/Model.qll +++ /dev/null @@ -1,79 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "mysql.Connection;mysql.Pool;Member[on,addListener].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]", // - "mysql.Connection;mysql.PoolConnection;", // - "mysql.Connection;mysql.Query;Member[RowDataPacket].Argument[2]", // - "mysql.Connection;mysql;Member[createConnection].ReturnValue", // - "mysql.ConnectionConfig;mysql.Connection;Member[config]", // - "mysql.ConnectionConfig;mysql.PoolConfig;", // - "mysql.ConnectionConfig;mysql;Member[createConnection].Argument[0]", // - "mysql.ConnectionOptions;mysql.Connection;Member[changeUser].WithArity[1,2].Argument[0]", // - "mysql.ConnectionOptions;mysql.ConnectionConfig;", // - "mysql.Pool;mysql.PoolCluster;Member[of].ReturnValue", // - "mysql.Pool;mysql;Member[createPool].ReturnValue", // - "mysql.PoolCluster;mysql;Member[createPoolCluster].ReturnValue", // - "mysql.PoolConfig;mysql.PoolCluster;Member[add].Argument[1]", // - "mysql.PoolConfig;mysql.PoolCluster;Member[add].WithArity[1].Argument[0]", // - "mysql.PoolConfig;mysql;Member[createPool].Argument[0]", // - "mysql.PoolConnection;mysql.Pool;Member[acquireConnection].Argument[0]", // - "mysql.PoolConnection;mysql.Pool;Member[acquireConnection].Argument[1].Argument[1]", // - "mysql.PoolConnection;mysql.Pool;Member[getConnection].Argument[0].Argument[1]", // - "mysql.PoolConnection;mysql.PoolCluster;Member[getConnection].Argument[1,2].Argument[1]", // - "mysql.PoolConnection;mysql.PoolCluster;Member[getConnection].WithArity[1].Argument[0].Argument[1]", // - "mysql.Query;mysql.Query;Member[on].ReturnValue", // - "mysql.Query;mysql.QueryFunction;ReturnValue", // - "mysql.Query;mysql.QueryFunction;WithArity[1].Argument[0]", // - "mysql.QueryFunction;mysql.Connection;Member[createQuery,query]", // - "mysql.QueryFunction;mysql.Pool;Member[query]", // - "mysql2.Connection;mysql2.PoolConnection;", // - "mysql2.Connection;mysql2.authPlugins;Argument[0].Member[connection]", // - "mysql2.Connection;mysql2;Member[createConnection].ReturnValue", // - "mysql2.ConnectionOptions;mysql2.PoolOptions;", // - "mysql2.ConnectionOptions;mysql2/promise.Connection;Member[changeUser].Argument[0]", // - "mysql2.ConnectionOptions;mysql2/promise.Connection;Member[config]", // - "mysql2.ConnectionOptions;mysql2/promise;Member[createConnection].Argument[0]", // - "mysql2.ConnectionOptions;mysql2;Member[createConnection].Argument[0]", // - "mysql2.Pool;mysql2.Pool;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", // - "mysql2.Pool;mysql2;Member[createPool].ReturnValue", // - "mysql2.PoolConnection;mysql2.Pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]", // - "mysql2.PoolConnection;mysql2.Pool;Member[getConnection].Argument[0].Argument[1]", // - "mysql2.PoolOptions;mysql2/promise;Member[createPool].Argument[0]", // - "mysql2.PoolOptions;mysql2;Member[createPool].Argument[0]", // - "mysql2.authPlugins;mysql2.ConnectionOptions;Member[authPlugins].AnyMember", // - "mysql2/promise.Connection;mysql2.Connection;Member[promise].ReturnValue", // - "mysql2/promise.Connection;mysql2/promise.PoolConnection;", // - "mysql2/promise.Connection;mysql2/promise;Member[createConnectionPromise].ReturnValue.Awaited", // - "mysql2/promise.Connection;mysql2/promise;Member[createConnection].ReturnValue.Awaited", // - "mysql2/promise.Connection;mysql2;Member[createConnectionPromise].ReturnValue.Awaited", // - "mysql2/promise.Pool;mysql2.Pool;Member[promise].ReturnValue", // - "mysql2/promise.Pool;mysql2/promise.Pool;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", // - "mysql2/promise.Pool;mysql2/promise;Member[createPool].ReturnValue", // - "mysql2/promise.PoolConnection;mysql2.PoolConnection;Member[promise].ReturnValue", // - "mysql2/promise.PoolConnection;mysql2/promise.Pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]", // - "mysql2/promise.PoolConnection;mysql2/promise.Pool;Member[getConnection].ReturnValue.Awaited", // - "mysql2/typings/mysql.Connection;mysql2.Connection;", // - "mysql2/typings/mysql.Connection;mysql2.Pool;", // - "mysql2/typings/mysql.PoolConnection;mysql2.PoolConnection;", // - "mysql2/typings/mysql/lib/Connection;mysql2/typings/mysql.Connection;", // - "mysql2/typings/mysql/lib/Connection;mysql2/typings/mysql/lib/PoolConnection;", // - "mysql2/typings/mysql/lib/PoolConnection;mysql2/typings/mysql.PoolConnection;", // - ] - } -} - -private class Summaries extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "mysql2.Pool;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - "mysql2/promise.Pool;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - "mysql2/typings/mysql/lib/Connection;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/mysql/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/mysql/model.yml new file mode 100644 index 00000000000..506dc42b7c3 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/mysql/model.yml @@ -0,0 +1,70 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [mysql.Connection, mysql.Pool, "Member[on,addListener].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]"] + - [mysql.Connection, mysql.PoolConnection, ""] + - [mysql.Connection, mysql.Query, "Member[RowDataPacket].Argument[2]"] + - [mysql.Connection, mysql, "Member[createConnection].ReturnValue"] + - [mysql.ConnectionConfig, mysql.Connection, "Member[config]"] + - [mysql.ConnectionConfig, mysql.PoolConfig, ""] + - [mysql.ConnectionConfig, mysql, "Member[createConnection].Argument[0]"] + - [mysql.ConnectionOptions, mysql.Connection, "Member[changeUser].WithArity[1,2].Argument[0]"] + - [mysql.ConnectionOptions, mysql.ConnectionConfig, ""] + - [mysql.Pool, mysql.PoolCluster, "Member[of].ReturnValue"] + - [mysql.Pool, mysql, "Member[createPool].ReturnValue"] + - [mysql.PoolCluster, mysql, "Member[createPoolCluster].ReturnValue"] + - [mysql.PoolConfig, mysql.PoolCluster, "Member[add].Argument[1]"] + - [mysql.PoolConfig, mysql.PoolCluster, "Member[add].WithArity[1].Argument[0]"] + - [mysql.PoolConfig, mysql, "Member[createPool].Argument[0]"] + - [mysql.PoolConnection, mysql.Pool, "Member[acquireConnection].Argument[0]"] + - [mysql.PoolConnection, mysql.Pool, "Member[acquireConnection].Argument[1].Argument[1]"] + - [mysql.PoolConnection, mysql.Pool, "Member[getConnection].Argument[0].Argument[1]"] + - [mysql.PoolConnection, mysql.PoolCluster, "Member[getConnection].Argument[1,2].Argument[1]"] + - [mysql.PoolConnection, mysql.PoolCluster, "Member[getConnection].WithArity[1].Argument[0].Argument[1]"] + - [mysql.Query, mysql.Query, "Member[on].ReturnValue"] + - [mysql.Query, mysql.QueryFunction, ReturnValue] + - [mysql.Query, mysql.QueryFunction, "WithArity[1].Argument[0]"] + - [mysql.QueryFunction, mysql.Connection, "Member[createQuery,query]"] + - [mysql.QueryFunction, mysql.Pool, "Member[query]"] + - [mysql2.Connection, mysql2.PoolConnection, ""] + - [mysql2.Connection, mysql2.authPlugins, "Argument[0].Member[connection]"] + - [mysql2.Connection, mysql2, "Member[createConnection].ReturnValue"] + - [mysql2.ConnectionOptions, mysql2.PoolOptions, ""] + - [mysql2.ConnectionOptions, "mysql2/promise.Connection", "Member[changeUser].Argument[0]"] + - [mysql2.ConnectionOptions, "mysql2/promise.Connection", "Member[config]"] + - [mysql2.ConnectionOptions, "mysql2/promise", "Member[createConnection].Argument[0]"] + - [mysql2.ConnectionOptions, mysql2, "Member[createConnection].Argument[0]"] + - [mysql2.Pool, mysql2.Pool, "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue"] + - [mysql2.Pool, mysql2, "Member[createPool].ReturnValue"] + - [mysql2.PoolConnection, mysql2.Pool, "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]"] + - [mysql2.PoolConnection, mysql2.Pool, "Member[getConnection].Argument[0].Argument[1]"] + - [mysql2.PoolOptions, "mysql2/promise", "Member[createPool].Argument[0]"] + - [mysql2.PoolOptions, mysql2, "Member[createPool].Argument[0]"] + - [mysql2.authPlugins, mysql2.ConnectionOptions, "Member[authPlugins].AnyMember"] + - ["mysql2/promise.Connection", mysql2.Connection, "Member[promise].ReturnValue"] + - ["mysql2/promise.Connection", "mysql2/promise.PoolConnection", ""] + - ["mysql2/promise.Connection", "mysql2/promise", "Member[createConnectionPromise].ReturnValue.Awaited"] + - ["mysql2/promise.Connection", "mysql2/promise", "Member[createConnection].ReturnValue.Awaited"] + - ["mysql2/promise.Connection", mysql2, "Member[createConnectionPromise].ReturnValue.Awaited"] + - ["mysql2/promise.Pool", mysql2.Pool, "Member[promise].ReturnValue"] + - ["mysql2/promise.Pool", "mysql2/promise.Pool", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue"] + - ["mysql2/promise.Pool", "mysql2/promise", "Member[createPool].ReturnValue"] + - ["mysql2/promise.PoolConnection", mysql2.PoolConnection, "Member[promise].ReturnValue"] + - ["mysql2/promise.PoolConnection", "mysql2/promise.Pool", "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connection,0=release].Argument[1].Argument[0]"] + - ["mysql2/promise.PoolConnection", "mysql2/promise.Pool", "Member[getConnection].ReturnValue.Awaited"] + - ["mysql2/typings/mysql.Connection", mysql2.Connection, ""] + - ["mysql2/typings/mysql.Connection", mysql2.Pool, ""] + - ["mysql2/typings/mysql.PoolConnection", mysql2.PoolConnection, ""] + - ["mysql2/typings/mysql/lib/Connection", "mysql2/typings/mysql.Connection", ""] + - ["mysql2/typings/mysql/lib/Connection", "mysql2/typings/mysql/lib/PoolConnection", ""] + - ["mysql2/typings/mysql/lib/PoolConnection", "mysql2/typings/mysql.PoolConnection", ""] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [mysql2.Pool, "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + - ["mysql2/promise.Pool", "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + - ["mysql2/typings/mysql/lib/Connection", "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/pg/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/pg/Model.qll deleted file mode 100644 index 979b98bd0c5..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/pg/Model.qll +++ /dev/null @@ -1,120 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "events;pg-cursor;", // - "events;pg-promise/pg-subset.pg.IClient;", // - "events;pg-promise/pg-subset.pg.IConnection;", // - "events;pg-promise/pg-subset.pg.IPool;", // - "events;pg.ClientBase;", // - "events;pg.Events;", // - "events;pg.Pool;", // - "global.NodeJS.EventEmitter;events;", // - "pg-cursor.Static;pg-cursor;", // - "pg-cursor;pg-cursor.Static;Instance", // - "pg-pool.Static;pg-pool;", // - "pg-pool;pg-pool.Static;Instance", // - "pg-pool;pg-pool;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", // - "pg-promise.IBaseProtocol;pg-promise.IConnected;", // - "pg-promise.IBaseProtocol;pg-promise.IDatabase;", // - "pg-promise.IBaseProtocol;pg-promise.ITask;", // - "pg-promise.IBaseProtocol;pg-promise/typescript/pg-promise.IBaseProtocol;", // - "pg-promise.IConnected;pg-promise.IDatabase;Member[connect].ReturnValue.Awaited", // - "pg-promise.IConnected;pg-promise/typescript/pg-promise.IConnected;", // - "pg-promise.IDatabase;pg-promise.IInitOptions;Member[extend].Argument[0]", // - "pg-promise.IDatabase;pg-promise.IMain;ReturnValue", // - "pg-promise.IDatabase;pg-promise/typescript/pg-promise.IDatabase;", // - "pg-promise.IInitOptions;pg-promise.ILibConfig;Member[options]", // - "pg-promise.IInitOptions;pg-promise/typescript/pg-promise.IInitOptions;", // - "pg-promise.IInitOptions;pg-promise;Argument[0]", // - "pg-promise.ILibConfig;pg-promise.IDatabase;Member[$config]", // - "pg-promise.ILibConfig;pg-promise/typescript/pg-promise.ILibConfig;", // - "pg-promise.IMain;pg-promise.ILibConfig;Member[pgp]", // - "pg-promise.IMain;pg-promise/typescript/pg-promise.IMain;", // - "pg-promise.IMain;pg-promise;ReturnValue", // - "pg-promise.ITask;pg-promise.IBaseProtocol;Member[task,taskIf,tx,txIf].Argument[1].Argument[0]", // - "pg-promise.ITask;pg-promise.IBaseProtocol;Member[task,taskIf,tx,txIf].WithArity[1].Argument[0].Argument[0]", // - "pg-promise.ITask;pg-promise.IBaseProtocol;Member[taskIf].WithArity[2].Argument[0].Member[cnd].Argument[0]", // - "pg-promise.ITask;pg-promise.IBaseProtocol;Member[txIf].WithArity[2].Argument[0].Member[cnd,reusable].Argument[0]", // - "pg-promise.ITask;pg-promise/typescript/pg-promise.ITask;", // - "pg-promise/pg-subset.pg.IClient;pg-promise.IMain;Argument[0].TypeVar[pg-promise/pg-subset.pg.IConnectionParameters.0]", // - "pg-promise/pg-subset.pg.IClient;pg-promise.IMain;ReturnValue.TypeVar[pg-promise.IDatabase.1]", // - "pg-promise/pg-subset.pg.IClient;pg-promise/pg-subset;Member[Client].Instance", // - "pg-promise/pg-subset.pg.IClient;pg-promise;Argument[0].TypeVar[pg-promise.IInitOptions.1]", // - "pg-promise/pg-subset.pg.IConnection;pg-promise/pg-subset.pg.IClient;Member[connection]", // - "pg-promise/pg-subset.pg.IPool;pg-promise.IDatabase;Member[$pool]", // - "pg.Client;pg-pool.Static;Instance.TypeVar[pg-pool.0]", // - "pg.Client;pg-promise/pg-subset.pg.IClient;", // - "pg.Client;pg.ClientStatic;Instance", // - "pg.Client;pg.Events;Member[addListener,on,once,prependListener,prependOnceListener].Argument[1].Argument[1]", // - "pg.ClientBase;pg.Client;", // - "pg.ClientBase;pg.PoolClient;", // - "pg.ClientStatic;pg;Member[Client]", // - "pg.Connection;pg-promise/pg-subset.pg.IConnection;", // - "pg.Events;pg.Events;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", // - "pg.Events;pg.EventsStatic;Instance", // - "pg.EventsStatic;pg;Member[Events]", // - "pg.Pool;pg-pool;", // - "pg.Pool;pg-promise/pg-subset.pg.IPool;", // - "pg.Pool;pg.Pool;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", // - "pg.Pool;pg.PoolStatic;Instance", // - "pg.PoolClient;pg-pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]", // - "pg.PoolClient;pg-pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]", // - "pg.PoolClient;pg-pool;Member[connect].Argument[0].Argument[1]", // - "pg.PoolClient;pg-pool;Member[connect].WithArity[0].ReturnValue.Awaited", // - "pg.PoolClient;pg.Pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]", // - "pg.PoolClient;pg.Pool;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]", // - "pg.PoolClient;pg.Pool;Member[connect].Argument[0].Argument[1]", // - "pg.PoolClient;pg.Pool;Member[connect].WithArity[0].ReturnValue.Awaited", // - "pg.PoolStatic;pg;Member[Pool]", // - ] - } -} - -private class Summaries extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "global.NodeJS.EventEmitter;;;Member[addListener,off,on,once,prependListener,prependOnceListener,removeAllListeners,removeListener,setMaxListeners].ReturnValue;type", // - "pg-pool;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - "pg.ClientBase;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - "pg.Events;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - "pg.Pool;;;Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue;type", // - ] - } -} - -private class TypeVariables extends ModelInput::TypeVariableModelCsv { - override predicate row(string row) { - row = - [ - "pg-pool.0;Member[Client].TypeVar[pg-pool.ClientLikeCtr.0]", // - "pg-pool.0;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]", // - "pg-pool.0;Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]", // - "pg-pool.0;Member[connect].Argument[0].Argument[1]", // - "pg-pool.0;Member[connect].WithArity[0].ReturnValue.Awaited", // - "pg-pool.ClientLikeCtr.0;Instance", // - "pg-promise.IConnected.1;Member[client]", // - "pg-promise.IConnectionOptions.0;Member[onLost].Argument[1].TypeVar[pg-promise.ILostContext.0]", // - "pg-promise.IDatabase.1;Member[$cn].TypeVar[pg-promise/pg-subset.pg.IConnectionParameters.0]", // - "pg-promise.IDatabase.1;Member[$config].TypeVar[pg-promise.ILibConfig.1]", // - "pg-promise.IDatabase.1;Member[connect].Argument[0].TypeVar[pg-promise.IConnectionOptions.0]", // - "pg-promise.IDatabase.1;Member[connect].ReturnValue.Awaited.TypeVar[pg-promise.IConnected.1]", // - "pg-promise.IEventContext.0;Member[client]", // - "pg-promise.IInitOptions.1;Member[connect,disconnect].Argument[0]", // - "pg-promise.IInitOptions.1;Member[error].Argument[1].TypeVar[pg-promise.IEventContext.0]", // - "pg-promise.IInitOptions.1;Member[extend].Argument[0].TypeVar[pg-promise.IDatabase.1]", // - "pg-promise.IInitOptions.1;Member[query,task,transact].Argument[0].TypeVar[pg-promise.IEventContext.0]", // - "pg-promise.IInitOptions.1;Member[receive].Argument[2].TypeVar[pg-promise.IEventContext.0]", // - "pg-promise.ILibConfig.1;Member[options].TypeVar[pg-promise.IInitOptions.1]", // - "pg-promise.ILibConfig.1;Member[pgp].TypeVar[pg-promise.IMain.1]", // - "pg-promise.ILostContext.0;Member[client]", // - "pg-promise/pg-promise.XPromise.0;Awaited", // - "pg-promise/pg-subset.pg.IConnectionParameters.0;Member[Client].Instance", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/pg/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/pg/model.yml new file mode 100644 index 00000000000..27207b6aff9 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/pg/model.yml @@ -0,0 +1,108 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [events, "pg-cursor", ""] + - [events, "pg-promise/pg-subset.pg.IClient", ""] + - [events, "pg-promise/pg-subset.pg.IConnection", ""] + - [events, "pg-promise/pg-subset.pg.IPool", ""] + - [events, pg.ClientBase, ""] + - [events, pg.Events, ""] + - [events, pg.Pool, ""] + - [global.NodeJS.EventEmitter, events, ""] + - ["pg-cursor.Static", "pg-cursor", ""] + - ["pg-cursor", "pg-cursor.Static", Instance] + - ["pg-pool.Static", "pg-pool", ""] + - ["pg-pool", "pg-pool.Static", Instance] + - ["pg-pool", "pg-pool", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue"] + - ["pg-promise.IBaseProtocol", "pg-promise.IConnected", ""] + - ["pg-promise.IBaseProtocol", "pg-promise.IDatabase", ""] + - ["pg-promise.IBaseProtocol", "pg-promise.ITask", ""] + - ["pg-promise.IBaseProtocol", "pg-promise/typescript/pg-promise.IBaseProtocol", ""] + - ["pg-promise.IConnected", "pg-promise.IDatabase", "Member[connect].ReturnValue.Awaited"] + - ["pg-promise.IConnected", "pg-promise/typescript/pg-promise.IConnected", ""] + - ["pg-promise.IDatabase", "pg-promise.IInitOptions", "Member[extend].Argument[0]"] + - ["pg-promise.IDatabase", "pg-promise.IMain", ReturnValue] + - ["pg-promise.IDatabase", "pg-promise/typescript/pg-promise.IDatabase", ""] + - ["pg-promise.IInitOptions", "pg-promise.ILibConfig", "Member[options]"] + - ["pg-promise.IInitOptions", "pg-promise/typescript/pg-promise.IInitOptions", ""] + - ["pg-promise.IInitOptions", "pg-promise", "Argument[0]"] + - ["pg-promise.ILibConfig", "pg-promise.IDatabase", "Member[$config]"] + - ["pg-promise.ILibConfig", "pg-promise/typescript/pg-promise.ILibConfig", ""] + - ["pg-promise.IMain", "pg-promise.ILibConfig", "Member[pgp]"] + - ["pg-promise.IMain", "pg-promise/typescript/pg-promise.IMain", ""] + - ["pg-promise.IMain", "pg-promise", ReturnValue] + - ["pg-promise.ITask", "pg-promise.IBaseProtocol", "Member[task,taskIf,tx,txIf].Argument[1].Argument[0]"] + - ["pg-promise.ITask", "pg-promise.IBaseProtocol", "Member[task,taskIf,tx,txIf].WithArity[1].Argument[0].Argument[0]"] + - ["pg-promise.ITask", "pg-promise.IBaseProtocol", "Member[taskIf].WithArity[2].Argument[0].Member[cnd].Argument[0]"] + - ["pg-promise.ITask", "pg-promise.IBaseProtocol", "Member[txIf].WithArity[2].Argument[0].Member[cnd,reusable].Argument[0]"] + - ["pg-promise.ITask", "pg-promise/typescript/pg-promise.ITask", ""] + - ["pg-promise/pg-subset.pg.IClient", "pg-promise.IMain", "Argument[0].TypeVar[pg-promise/pg-subset.pg.IConnectionParameters.0]"] + - ["pg-promise/pg-subset.pg.IClient", "pg-promise.IMain", "ReturnValue.TypeVar[pg-promise.IDatabase.1]"] + - ["pg-promise/pg-subset.pg.IClient", "pg-promise/pg-subset", "Member[Client].Instance"] + - ["pg-promise/pg-subset.pg.IClient", "pg-promise", "Argument[0].TypeVar[pg-promise.IInitOptions.1]"] + - ["pg-promise/pg-subset.pg.IConnection", "pg-promise/pg-subset.pg.IClient", "Member[connection]"] + - ["pg-promise/pg-subset.pg.IPool", "pg-promise.IDatabase", "Member[$pool]"] + - [pg.Client, "pg-pool.Static", "Instance.TypeVar[pg-pool.0]"] + - [pg.Client, "pg-promise/pg-subset.pg.IClient", ""] + - [pg.Client, pg.ClientStatic, Instance] + - [pg.Client, pg.Events, "Member[addListener,on,once,prependListener,prependOnceListener].Argument[1].Argument[1]"] + - [pg.ClientBase, pg.Client, ""] + - [pg.ClientBase, pg.PoolClient, ""] + - [pg.ClientStatic, pg, "Member[Client]"] + - [pg.Connection, "pg-promise/pg-subset.pg.IConnection", ""] + - [pg.Events, pg.Events, "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue"] + - [pg.Events, pg.EventsStatic, Instance] + - [pg.EventsStatic, pg, "Member[Events]"] + - [pg.Pool, "pg-pool", ""] + - [pg.Pool, "pg-promise/pg-subset.pg.IPool", ""] + - [pg.Pool, pg.Pool, "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue"] + - [pg.Pool, pg.PoolStatic, Instance] + - [pg.PoolClient, "pg-pool", "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]"] + - [pg.PoolClient, "pg-pool", "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]"] + - [pg.PoolClient, "pg-pool", "Member[connect].Argument[0].Argument[1]"] + - [pg.PoolClient, "pg-pool", "Member[connect].WithArity[0].ReturnValue.Awaited"] + - [pg.PoolClient, pg.Pool, "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]"] + - [pg.PoolClient, pg.Pool, "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]"] + - [pg.PoolClient, pg.Pool, "Member[connect].Argument[0].Argument[1]"] + - [pg.PoolClient, pg.Pool, "Member[connect].WithArity[0].ReturnValue.Awaited"] + - [pg.PoolStatic, pg, "Member[Pool]"] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [global.NodeJS.EventEmitter, "", "", "Member[addListener,off,on,once,prependListener,prependOnceListener,removeAllListeners,removeListener,setMaxListeners].ReturnValue", type] + - ["pg-pool", "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + - [pg.ClientBase, "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + - [pg.Events, "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + - [pg.Pool, "", "", "Member[addListener,on,once,prependListener,prependOnceListener].ReturnValue", type] + + - addsTo: + pack: codeql/javascript-all + extensible: typeVariableModel + data: + - ["pg-pool.0", "Member[Client].TypeVar[pg-pool.ClientLikeCtr.0]"] + - ["pg-pool.0", "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=acquire,0=connect,0=remove].Argument[1].Argument[0]"] + - ["pg-pool.0", "Member[addListener,on,once,prependListener,prependOnceListener].WithArity[2].WithStringArgument[0=error].Argument[1].Argument[1]"] + - ["pg-pool.0", "Member[connect].Argument[0].Argument[1]"] + - ["pg-pool.0", "Member[connect].WithArity[0].ReturnValue.Awaited"] + - ["pg-pool.ClientLikeCtr.0", Instance] + - ["pg-promise.IConnected.1", "Member[client]"] + - ["pg-promise.IConnectionOptions.0", "Member[onLost].Argument[1].TypeVar[pg-promise.ILostContext.0]"] + - ["pg-promise.IDatabase.1", "Member[$cn].TypeVar[pg-promise/pg-subset.pg.IConnectionParameters.0]"] + - ["pg-promise.IDatabase.1", "Member[$config].TypeVar[pg-promise.ILibConfig.1]"] + - ["pg-promise.IDatabase.1", "Member[connect].Argument[0].TypeVar[pg-promise.IConnectionOptions.0]"] + - ["pg-promise.IDatabase.1", "Member[connect].ReturnValue.Awaited.TypeVar[pg-promise.IConnected.1]"] + - ["pg-promise.IEventContext.0", "Member[client]"] + - ["pg-promise.IInitOptions.1", "Member[connect,disconnect].Argument[0]"] + - ["pg-promise.IInitOptions.1", "Member[error].Argument[1].TypeVar[pg-promise.IEventContext.0]"] + - ["pg-promise.IInitOptions.1", "Member[extend].Argument[0].TypeVar[pg-promise.IDatabase.1]"] + - ["pg-promise.IInitOptions.1", "Member[query,task,transact].Argument[0].TypeVar[pg-promise.IEventContext.0]"] + - ["pg-promise.IInitOptions.1", "Member[receive].Argument[2].TypeVar[pg-promise.IEventContext.0]"] + - ["pg-promise.ILibConfig.1", "Member[options].TypeVar[pg-promise.IInitOptions.1]"] + - ["pg-promise.ILibConfig.1", "Member[pgp].TypeVar[pg-promise.IMain.1]"] + - ["pg-promise.ILostContext.0", "Member[client]"] + - ["pg-promise/pg-promise.XPromise.0", Awaited] + - ["pg-promise/pg-subset.pg.IConnectionParameters.0", "Member[Client].Instance"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/sequelize/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/sequelize/Model.qll deleted file mode 100644 index ba4d9669661..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/sequelize/Model.qll +++ /dev/null @@ -1,297 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Sinks extends ModelInput::SinkModelCsv { - override predicate row(string row) { - row = - [ - "sequelize.Sequelize;Member[query].Argument[0].Member[query];sql-injection", // - "sequelize.Sequelize;Member[query].Argument[0];sql-injection", // - "sequelize.SequelizeStaticAndInstance;Member[asIs,literal].Argument[0];sql-injection", // - "sequelize;Argument[0..].Member[password];credentials[password]", // - "sequelize;Argument[0..].Member[username];credentials[username]", // - "sequelize;Argument[1];credentials[username]", // - "sequelize;Argument[2];credentials[password]", // - ] - } -} - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "sequelize-typescript.AssociationCountOptions;sequelize-typescript.Model;Member[$count].Argument[1]", // - "sequelize-typescript.AssociationCountOptions;sequelize-typescript/model/model/association/association-count-options.AssociationCountOptions;", // - "sequelize-typescript.AssociationGetOptions;sequelize-typescript.Model;Member[$get].Argument[1]", // - "sequelize-typescript.AssociationGetOptions;sequelize-typescript.Model;Member[$has].Argument[2]", // - "sequelize-typescript.AssociationGetOptions;sequelize-typescript/model/model/association/association-get-options.AssociationGetOptions;", // - "sequelize-typescript.BaseAssociation;sequelize-typescript.BaseAssociationStatic;Instance", // - "sequelize-typescript.BaseAssociation;sequelize-typescript.BelongsToAssociation;", // - "sequelize-typescript.BaseAssociation;sequelize-typescript.BelongsToManyAssociation;", // - "sequelize-typescript.BaseAssociation;sequelize-typescript.HasAssociation;", // - "sequelize-typescript.BaseAssociation;sequelize-typescript/associations/shared/association-service;Member[addAssociation].Argument[1]", // - "sequelize-typescript.BaseAssociation;sequelize-typescript/associations/shared/association-service;Member[getAssociations,getAssociationsByRelation].ReturnValue.ArrayElement", // - "sequelize-typescript.BaseAssociation;sequelize-typescript/associations/shared/association-service;Member[setAssociations].Argument[1].ArrayElement", // - "sequelize-typescript.BaseAssociation;sequelize-typescript/associations/shared/base-association.BaseAssociation;", // - "sequelize-typescript.BaseAssociation;sequelize-typescript;Member[addAssociation].Argument[1]", // - "sequelize-typescript.BaseAssociation;sequelize-typescript;Member[getAssociations,getAssociationsByRelation].ReturnValue.ArrayElement", // - "sequelize-typescript.BaseAssociation;sequelize-typescript;Member[setAssociations].Argument[1].ArrayElement", // - "sequelize-typescript.BaseAssociationStatic;sequelize-typescript/associations/shared/base-association.BaseAssociationStatic;", // - "sequelize-typescript.BaseAssociationStatic;sequelize-typescript/associations/shared/base-association;Member[BaseAssociation]", // - "sequelize-typescript.BaseAssociationStatic;sequelize-typescript;Member[BaseAssociation]", // - "sequelize-typescript.BelongsToAssociation;sequelize-typescript.BelongsToAssociationStatic;Instance", // - "sequelize-typescript.BelongsToAssociation;sequelize-typescript/associations/belongs-to/belongs-to-association.BelongsToAssociation;", // - "sequelize-typescript.BelongsToAssociationStatic;sequelize-typescript/associations/belongs-to/belongs-to-association.BelongsToAssociationStatic;", // - "sequelize-typescript.BelongsToAssociationStatic;sequelize-typescript/associations/belongs-to/belongs-to-association;Member[BelongsToAssociation]", // - "sequelize-typescript.BelongsToAssociationStatic;sequelize-typescript;Member[BelongsToAssociation]", // - "sequelize-typescript.BelongsToManyAssociation;sequelize-typescript.BelongsToManyAssociationStatic;Instance", // - "sequelize-typescript.BelongsToManyAssociation;sequelize-typescript/associations/belongs-to-many/belongs-to-many-association.BelongsToManyAssociation;", // - "sequelize-typescript.BelongsToManyAssociationStatic;sequelize-typescript/associations/belongs-to-many/belongs-to-many-association.BelongsToManyAssociationStatic;", // - "sequelize-typescript.BelongsToManyAssociationStatic;sequelize-typescript/associations/belongs-to-many/belongs-to-many-association;Member[BelongsToManyAssociation]", // - "sequelize-typescript.BelongsToManyAssociationStatic;sequelize-typescript;Member[BelongsToManyAssociation]", // - "sequelize-typescript.DefaultScopeGetter;sequelize-typescript.ScopeOptionsGetters;Member[getDefaultScope]", // - "sequelize-typescript.DefaultScopeGetter;sequelize-typescript/scopes/default-scope;Member[DefaultScope].Argument[0]", // - "sequelize-typescript.DefaultScopeGetter;sequelize-typescript/scopes/scope-options.DefaultScopeGetter;", // - "sequelize-typescript.DefaultScopeGetter;sequelize-typescript;Member[DefaultScope].Argument[0]", // - "sequelize-typescript.HasAssociation;sequelize-typescript.HasAssociationStatic;Instance", // - "sequelize-typescript.HasAssociation;sequelize-typescript/associations/has/has-association.HasAssociation;", // - "sequelize-typescript.HasAssociationStatic;sequelize-typescript/associations/has/has-association.HasAssociationStatic;", // - "sequelize-typescript.HasAssociationStatic;sequelize-typescript/associations/has/has-association;Member[HasAssociation]", // - "sequelize-typescript.HasAssociationStatic;sequelize-typescript;Member[HasAssociation]", // - "sequelize-typescript.Model;sequelize-typescript.Model;Member[$add,$has,$remove,$set].Argument[1]", // - "sequelize-typescript.Model;sequelize-typescript.Model;Member[$add,$has,$remove,$set].Argument[1].ArrayElement", // - "sequelize-typescript.Model;sequelize-typescript.Model;Member[$create,reload].ReturnValue.Awaited", // - "sequelize-typescript.Model;sequelize-typescript.ModelStatic~;Instance", // - "sequelize-typescript.Model;sequelize-typescript.ModelStatic~;Member[initialize].ReturnValue.TypeVar[sequelize-typescript.ModelStatic.0]", // - "sequelize-typescript.Model;sequelize-typescript.ModelType;Instance", // - "sequelize-typescript.Model;sequelize-typescript.Sequelize;Member[getRepository].Argument[0].Instance", // - "sequelize-typescript.Model;sequelize-typescript.Sequelize;Member[getRepository].ReturnValue.TypeVar[sequelize-typescript.Repository.0]", // - "sequelize-typescript.Model;sequelize-typescript/model/model/model.Model;", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript.BaseAssociationStatic;Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript.BelongsToAssociationStatic;Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript.BelongsToManyAssociationStatic;Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript.HasAssociationStatic;Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/belongs-to-many/belongs-to-many;Member[BelongsToMany].Argument[0,1]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/belongs-to/belongs-to;Member[BelongsTo].Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/foreign-key/foreign-key-meta.ForeignKeyMeta;Member[relatedClassGetter]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/foreign-key/foreign-key-service;Member[addForeignKey].Argument[1]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/foreign-key/foreign-key;Member[ForeignKey].Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/has/has-many;Member[HasMany].Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/associations/has/has-one;Member[HasOne].Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript/model/shared/model-class-getter.ModelClassGetter;", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript;Member[BelongsTo,ForeignKey,HasMany,HasOne].Argument[0]", // - "sequelize-typescript.ModelClassGetter;sequelize-typescript;Member[BelongsToMany].Argument[0,1]", // - "sequelize-typescript.ModelStatic~;sequelize-typescript/model/model/model.ModelStatic~;", // - "sequelize-typescript.ModelStatic~;sequelize-typescript/model/model/model;Member[Model]", // - "sequelize-typescript.ModelStatic~;sequelize-typescript/model/shared/model-not-initialized-error.ModelNotInitializedErrorStatic;Argument[0]", // - "sequelize-typescript.ModelStatic~;sequelize-typescript;Member[Model]", // - "sequelize-typescript.ModelType;sequelize-typescript.BaseAssociation;Member[getAssociatedClass].ReturnValue", // - "sequelize-typescript.ModelType;sequelize-typescript.BaseAssociation;Member[getSequelizeOptions].Argument[0]", // - "sequelize-typescript.ModelType;sequelize-typescript.BelongsToAssociation;Member[getSequelizeOptions].Argument[0]", // - "sequelize-typescript.ModelType;sequelize-typescript.BelongsToManyAssociation;Member[getSequelizeOptions].Argument[0]", // - "sequelize-typescript.ModelType;sequelize-typescript.HasAssociation;Member[getSequelizeOptions].Argument[0]", // - "sequelize-typescript.ModelType;sequelize-typescript.ModelClassGetter;ReturnValue", // - "sequelize-typescript.ModelType;sequelize-typescript.Sequelize;Member[model].Argument[0]", // - "sequelize-typescript.ModelType;sequelize-typescript/associations/foreign-key/foreign-key-service;Member[getForeignKeyOptions].Argument[0,1]", // - "sequelize-typescript.ModelType;sequelize-typescript/model/model/model.ModelType;", // - "sequelize-typescript.ScopeOptionsGetters;sequelize-typescript/scopes/scope-options.ScopeOptionsGetters;", // - "sequelize-typescript.ScopeOptionsGetters;sequelize-typescript/scopes/scope-service;Member[addScopeOptionsGetter,setScopeOptionsGetters].Argument[1]", // - "sequelize-typescript.ScopeOptionsGetters;sequelize-typescript/scopes/scope-service;Member[getScopeOptionsGetters].ReturnValue", // - "sequelize-typescript.ScopeOptionsGetters;sequelize-typescript;Member[addScopeOptionsGetter,setScopeOptionsGetters].Argument[1]", // - "sequelize-typescript.ScopeOptionsGetters;sequelize-typescript;Member[getScopeOptionsGetters].ReturnValue", // - "sequelize-typescript.ScopesOptions;sequelize-typescript.ScopesOptionsGetter;ReturnValue.AnyMember", // - "sequelize-typescript.ScopesOptions;sequelize-typescript/scopes/scope-options.ScopesOptions;", // - "sequelize-typescript.ScopesOptions;sequelize-typescript/scopes/scope-service;Member[resolveScope].Argument[2]", // - "sequelize-typescript.ScopesOptions;sequelize-typescript;Member[resolveScope].Argument[2]", // - "sequelize-typescript.ScopesOptionsGetter;sequelize-typescript.ScopeOptionsGetters;Member[getScopes]", // - "sequelize-typescript.ScopesOptionsGetter;sequelize-typescript/scopes/scope-options.ScopesOptionsGetter;", // - "sequelize-typescript.ScopesOptionsGetter;sequelize-typescript/scopes/scopes;Member[Scopes].Argument[0]", // - "sequelize-typescript.ScopesOptionsGetter;sequelize-typescript;Member[Scopes].Argument[0]", // - "sequelize-typescript.Sequelize;sequelize-typescript.BaseAssociation;Member[getSequelizeOptions].Argument[1]", // - "sequelize-typescript.Sequelize;sequelize-typescript.BelongsToManyAssociation;Member[getSequelizeOptions].Argument[1]", // - "sequelize-typescript.Sequelize;sequelize-typescript.SequelizeStatic;Instance", // - "sequelize-typescript.Sequelize;sequelize-typescript/sequelize/sequelize/sequelize.Sequelize;", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.Sequelize;Member[options]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.SequelizeStatic;Argument[3]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.SequelizeStatic;WithArity[0].Argument[0]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.SequelizeStatic;WithArity[1].Argument[0,1]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.SequelizeStatic;WithArity[2].Argument[1,2]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript.SequelizeStatic;WithArity[3].Argument[2]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript/sequelize/sequelize/sequelize-options.SequelizeOptions;", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript/sequelize/sequelize/sequelize-service;Member[prepareArgs].ReturnValue.Member[options]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript/sequelize/sequelize/sequelize-service;Member[prepareOptions].Argument[0]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript/sequelize/sequelize/sequelize-service;Member[prepareOptions].ReturnValue", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript;Member[prepareArgs].ReturnValue.Member[options]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript;Member[prepareOptions].Argument[0]", // - "sequelize-typescript.SequelizeOptions;sequelize-typescript;Member[prepareOptions].ReturnValue", // - "sequelize-typescript.SequelizeStatic;sequelize-typescript/sequelize/sequelize/sequelize.SequelizeStatic;", // - "sequelize-typescript.SequelizeStatic;sequelize-typescript/sequelize/sequelize/sequelize;Member[Sequelize]", // - "sequelize-typescript.SequelizeStatic;sequelize-typescript;Member[Sequelize]", // - "sequelize-typescript/associations/foreign-key/foreign-key-meta.ForeignKeyMeta;sequelize-typescript/associations/foreign-key/foreign-key-service;Member[getForeignKeys].ReturnValue.ArrayElement", // - "sequelize-typescript/model/model/association/association-create-options.AssociationCreateOptions;sequelize-typescript.Model;Member[$create].Argument[2]", // - "sequelize-typescript/model/shared/model-not-initialized-error.ModelNotInitializedErrorStatic;sequelize-typescript/model/shared/model-not-initialized-error;Member[ModelNotInitializedError]", // - "sequelize.AnyFindOptions;sequelize.BelongsToManyAddAssociationMixin;Argument[1]", // - "sequelize.AnyFindOptions;sequelize.BelongsToManyAddAssociationsMixin;Argument[1]", // - "sequelize.AnyFindOptions;sequelize.BelongsToManySetAssociationsMixin;Argument[1]", // - "sequelize.AnyFindOptions;sequelize.DefineOptions;Member[defaultScope]", // - "sequelize.AnyFindOptions;sequelize.DefineScopeOptions;AnyMember", // - "sequelize.AnyFindOptions;sequelize.HasManySetAssociationsMixin;Argument[1]", // - "sequelize.AnyFindOptions;sequelize.Instance;Member[reload].Argument[0]", // - "sequelize.AnyFindOptions;sequelize.Model;Member[addScope].Argument[1]", // - "sequelize.AssociationOptionsBelongsToMany;sequelize.Associations;Member[belongsToMany].Argument[1]", // - "sequelize.Associations;sequelize.Model;", // - "sequelize.Associations;sequelize.SequelizeStaticAndInstance.Model;", // - "sequelize.BuildOptions;sequelize-typescript.ModelStatic~;Argument[1]", // - "sequelize.BuildOptions;sequelize.CreateOptions;", // - "sequelize.BuildOptions;sequelize.Model;Member[build,bulkBuild].Argument[1]", // - "sequelize.CountOptions;sequelize.Model;Member[count].Argument[0]", // - "sequelize.CreateOptions;sequelize-typescript/model/model/association/association-create-options.AssociationCreateOptions;", // - "sequelize.CreateOptions;sequelize.BelongsToCreateAssociationMixin;Argument[1]", // - "sequelize.CreateOptions;sequelize.BelongsToManyCreateAssociationMixin;Argument[1]", // - "sequelize.CreateOptions;sequelize.HasManyCreateAssociationMixin;Argument[1]", // - "sequelize.CreateOptions;sequelize.HasOneCreateAssociationMixin;Argument[1]", // - "sequelize.CreateOptions;sequelize.Model;Member[create].Argument[1]", // - "sequelize.DefineAttributeColumnOptions;sequelize.DefineAttributes;AnyMember", // - "sequelize.DefineAttributeColumnOptions;sequelize.QueryInterface;Member[addColumn,changeColumn].Argument[2]", // - "sequelize.DefineAttributeColumnReferencesOptions;sequelize.DefineAttributeColumnOptions;Member[references]", // - "sequelize.DefineAttributes;sequelize.Hooks;Member[beforeDefine].Argument[1].Argument[0]", // - "sequelize.DefineAttributes;sequelize.Hooks;Member[beforeDefine].WithArity[1].Argument[0].Argument[0]", // - "sequelize.DefineAttributes;sequelize.QueryInterface;Member[createTable].Argument[1]", // - "sequelize.DefineOptions;sequelize.Options;Member[define]", // - "sequelize.DefineOptions;sequelize.Sequelize;Member[define].Argument[2]", // - "sequelize.DefineScopeOptions;sequelize.DefineOptions;Member[scopes]", // - "sequelize.FindCreateFindOptions;sequelize.Model;Member[findCreateFind].Argument[0]", // - "sequelize.FindOptions;sequelize-typescript.AssociationCountOptions;", // - "sequelize.FindOptions;sequelize-typescript.AssociationGetOptions;", // - "sequelize.FindOptions;sequelize-typescript.DefaultScopeGetter;ReturnValue", // - "sequelize.FindOptions;sequelize-typescript.Model;Member[reload].Argument[0]", // - "sequelize.FindOptions;sequelize-typescript.ScopesOptions;", // - "sequelize.FindOptions;sequelize-typescript.ScopesOptions;ReturnValue", // - "sequelize.FindOptions;sequelize.AnyFindOptions;", // - "sequelize.FindOptions;sequelize.FindCreateFindOptions;", // - "sequelize.FindOptions;sequelize.FindOrInitializeOptions;", // - "sequelize.FindOptions;sequelize.Model;Member[all,find,findAll,findAndCount,findAndCountAll,findOne].Argument[0]", // - "sequelize.FindOptionsOrderArray;sequelize.FindOptions;Member[order]", // - "sequelize.FindOptionsOrderArray;sequelize.FindOptions;Member[order].ArrayElement", // - "sequelize.FindOrInitializeOptions;sequelize.Model;Member[findOrBuild,findOrCreate,findOrInitialize].Argument[0]", // - "sequelize.HasManyGetAssociationsMixinOptions;sequelize.HasManyGetAssociationsMixin;Argument[0]", // - "sequelize.HasManyGetAssociationsMixinOptions;sequelize.HasManyHasAssociationMixin;Argument[1]", // - "sequelize.HasManyGetAssociationsMixinOptions;sequelize.HasManyHasAssociationsMixin;Argument[1]", // - "sequelize.Hooks;sequelize.Hooks;Member[addHook,hook,removeHook].ReturnValue", // - "sequelize.Hooks;sequelize.Model;", // - "sequelize.Hooks;sequelize.Sequelize;", // - "sequelize.Hooks;sequelize.SequelizeStaticAndInstance.Model;", // - "sequelize.IncludeAssociation;sequelize.Associations;Member[belongsTo,belongsToMany,hasMany,hasOne].ReturnValue", // - "sequelize.IncludeAssociation;sequelize.IncludeOptions;Member[association]", // - "sequelize.IncludeOptions;sequelize.BuildOptions;Member[include].ArrayElement", // - "sequelize.IncludeOptions;sequelize.CountOptions;Member[include]", // - "sequelize.IncludeOptions;sequelize.CountOptions;Member[include].ArrayElement", // - "sequelize.IncludeOptions;sequelize.FindOptions;Member[include]", // - "sequelize.IncludeOptions;sequelize.FindOptions;Member[include].ArrayElement", // - "sequelize.IncludeOptions;sequelize.HasManyGetAssociationsMixinOptions;Member[include]", // - "sequelize.IncludeOptions;sequelize.IncludeOptions;Member[include]", // - "sequelize.IncludeOptions;sequelize.IncludeOptions;Member[include].ArrayElement", // - "sequelize.Instance;sequelize.Instance;Member[decrement,increment,reload,save,update,updateAttributes].ReturnValue.Awaited", // - "sequelize.Instance;sequelize.Instance;Member[equalsOneOf].Argument[0].ArrayElement", // - "sequelize.Instance;sequelize.Instance;Member[equals].Argument[0]", // - "sequelize.Instance;sequelize.Instance;Member[set,setAttributes].ReturnValue", // - "sequelize.Instance;sequelize.Model;Member[Instance,build].ReturnValue", // - "sequelize.Instance;sequelize.Model;Member[all,bulkCreate,findAll].ReturnValue.Awaited.ArrayElement", // - "sequelize.Instance;sequelize.Model;Member[bulkBuild].ReturnValue.ArrayElement", // - "sequelize.Instance;sequelize.Model;Member[create,find,findById,findByPk,findByPrimary,findOne].ReturnValue.Awaited", // - "sequelize.Instance;sequelize.Model;Member[findAndCount,findAndCountAll].ReturnValue.Awaited.Member[rows].ArrayElement", // - "sequelize.Instance;sequelize.QueryInterface;Member[delete,increment,insert,update].Argument[0]", // - "sequelize.Instance;sequelize.QueryOptions;Member[instance]", // - "sequelize.Instance;sequelize.SequelizeStaticAndInstance;Member[Instance]", // - "sequelize.Model;sequelize.AssociationOptionsBelongsToMany;Member[through]", // - "sequelize.Model;sequelize.Associations;Member[belongsTo,belongsToMany,hasMany,hasOne].Argument[0]", // - "sequelize.Model;sequelize.BuildOptions;Member[include].ArrayElement", // - "sequelize.Model;sequelize.CountOptions;Member[include]", // - "sequelize.Model;sequelize.CountOptions;Member[include].ArrayElement", // - "sequelize.Model;sequelize.DefineAttributeColumnReferencesOptions;Member[model]", // - "sequelize.Model;sequelize.FindOptions;Member[include]", // - "sequelize.Model;sequelize.FindOptions;Member[include].ArrayElement", // - "sequelize.Model;sequelize.FindOptions;Member[lock].Member[of]", // - "sequelize.Model;sequelize.FindOptionsOrderArray;ArrayElement", // - "sequelize.Model;sequelize.FindOptionsOrderArray;ArrayElement.Member[model]", // - "sequelize.Model;sequelize.Hooks;Member[afterDefine].Argument[1].Argument[0]", // - "sequelize.Model;sequelize.Hooks;Member[afterDefine].WithArity[1].Argument[0].Argument[0]", // - "sequelize.Model;sequelize.IncludeAssociation;Member[source,target]", // - "sequelize.Model;sequelize.IncludeOptions;Member[include,model]", // - "sequelize.Model;sequelize.IncludeOptions;Member[include].ArrayElement", // - "sequelize.Model;sequelize.Instance;Member[Model]", // - "sequelize.Model;sequelize.Model;Member[schema,scope,unscoped].ReturnValue", // - "sequelize.Model;sequelize.Model;Member[sync].ReturnValue.Awaited", // - "sequelize.Model;sequelize.Models;AnyMember", // - "sequelize.Model;sequelize.ModelsHashInterface;AnyMember", // - "sequelize.Model;sequelize.QueryInterface;Member[bulkDelete,rawSelect,upsert].Argument[3]", // - "sequelize.Model;sequelize.QueryInterface;Member[select].Argument[0]", // - "sequelize.Model;sequelize.QueryOptions;Member[model]", // - "sequelize.Model;sequelize.Sequelize;Member[define,import,model].ReturnValue", // - "sequelize.Model;sequelize.Sequelize;Member[import].Argument[1].ReturnValue", // - "sequelize.Model;sequelize.SequelizeStaticAndInstance;Member[Model]", // - "sequelize.Model;sequelize.ThroughOptions;Member[model]", // - "sequelize.Model;sequelize.Utils;Member[mapOptionFieldNames].Argument[1]", // - "sequelize.Model;sequelize.Utils;Member[mapValueFieldNames].Argument[2]", // - "sequelize.Models;sequelize.Model;Member[associate].Argument[0]", // - "sequelize.ModelsHashInterface;sequelize.Sequelize;Member[models]", // - "sequelize.Options;sequelize-typescript.SequelizeOptions;", // - "sequelize.Options;sequelize.Sequelize;Member[options]", // - "sequelize.Options;sequelize.SequelizeStatic;Argument[3]", // - "sequelize.Options;sequelize.SequelizeStatic;WithArity[1].Argument[0,1]", // - "sequelize.Options;sequelize.SequelizeStatic;WithArity[2].Argument[1,2]", // - "sequelize.Options;sequelize.SequelizeStatic;WithArity[3].Argument[2]", // - "sequelize.QueryInterface;sequelize.Sequelize;Member[getQueryInterface].ReturnValue", // - "sequelize.QueryOptions;sequelize.Options;Member[query]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[bulkDelete,bulkInsert,createTable,select,setAutocommit,setIsolationLevel].Argument[2]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[bulkUpdate,delete,insert].Argument[3]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[commitTransaction,deferConstraints,dropTable,rawSelect,rollbackTransaction,showIndex,startTransaction].Argument[1]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[createFunction].Argument[5]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[dropAllEnums,dropAllTables,showAllSchemas,showAllTables].Argument[0]", // - "sequelize.QueryOptions;sequelize.QueryInterface;Member[increment,update,upsert].Argument[4]", // - "sequelize.QueryOptions;sequelize.Sequelize;Member[authenticate,validate].Argument[0]", // - "sequelize.QueryOptions;sequelize.Sequelize;Member[query].Argument[1]", // - "sequelize.Sequelize;sequelize-typescript.Sequelize;", // - "sequelize.Sequelize;sequelize.Hooks;Member[afterInit].Argument[1].Argument[0]", // - "sequelize.Sequelize;sequelize.Hooks;Member[afterInit].WithArity[1].Argument[0].Argument[0]", // - "sequelize.Sequelize;sequelize.Instance;Member[sequelize]", // - "sequelize.Sequelize;sequelize.QueryInterface;Member[sequelize]", // - "sequelize.Sequelize;sequelize.Sequelize;Member[import].Argument[1].Argument[0]", // - "sequelize.Sequelize;sequelize.SequelizeStatic;Instance", // - "sequelize.Sequelize;sequelize.SequelizeStatic;Member[useCLS].ReturnValue", // - "sequelize.SequelizeStatic;sequelize-typescript.Sequelize;", // - "sequelize.SequelizeStatic;sequelize.Sequelize;Member[Sequelize]", // - "sequelize.SequelizeStatic;sequelize.SequelizeStatic;Member[Sequelize,default]", // - "sequelize.SequelizeStatic;sequelize;", // - "sequelize.SequelizeStaticAndInstance.Model;sequelize-typescript.Model;", // - "sequelize.SequelizeStaticAndInstance;sequelize.Sequelize;", // - "sequelize.SequelizeStaticAndInstance;sequelize.SequelizeStatic;", // - "sequelize.ThroughOptions;sequelize.AssociationOptionsBelongsToMany;Member[through]", // - "sequelize.Utils;sequelize.SequelizeStaticAndInstance;Member[Utils]", // - ] - } -} - -private class Summaries extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "sequelize-typescript.Model;;;Member[reload].ReturnValue.Awaited;type", // - "sequelize.Instance;;;Member[decrement,increment,reload,save,update,updateAttributes].ReturnValue.Awaited;type", // - "sequelize.Instance;;;Member[set,setAttributes].ReturnValue;type", // - "sequelize.Model;;;Member[schema,scope,unscoped].ReturnValue;type", // - "sequelize.Model;;;Member[sync].ReturnValue.Awaited;type", // - ] - } -} - -private class TypeVariables extends ModelInput::TypeVariableModelCsv { - override predicate row(string row) { - row = - [ - "sequelize-typescript.ModelStatic.0;Instance", // - "sequelize-typescript.Repository.0;Instance", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/sequelize/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/sequelize/model.yml new file mode 100644 index 00000000000..41a97e63a76 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/sequelize/model.yml @@ -0,0 +1,282 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - [sequelize.Sequelize, "Member[query].Argument[0].Member[query]", "sql-injection"] + - [sequelize.Sequelize, "Member[query].Argument[0]", "sql-injection"] + - [sequelize.SequelizeStaticAndInstance, "Member[asIs,literal].Argument[0]", "sql-injection"] + - [sequelize, "Argument[0..].Member[password]", "credentials[password]"] + - [sequelize, "Argument[0..].Member[username]", "credentials[username]"] + - [sequelize, "Argument[1]", "credentials[username]"] + - [sequelize, "Argument[2]", "credentials[password]"] + + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - ["sequelize-typescript.AssociationCountOptions", "sequelize-typescript.Model", "Member[$count].Argument[1]"] + - ["sequelize-typescript.AssociationCountOptions", "sequelize-typescript/model/model/association/association-count-options.AssociationCountOptions", ""] + - ["sequelize-typescript.AssociationGetOptions", "sequelize-typescript.Model", "Member[$get].Argument[1]"] + - ["sequelize-typescript.AssociationGetOptions", "sequelize-typescript.Model", "Member[$has].Argument[2]"] + - ["sequelize-typescript.AssociationGetOptions", "sequelize-typescript/model/model/association/association-get-options.AssociationGetOptions", ""] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript.BaseAssociationStatic", Instance] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript.BelongsToAssociation", ""] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript.BelongsToManyAssociation", ""] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript.HasAssociation", ""] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript/associations/shared/association-service", "Member[addAssociation].Argument[1]"] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript/associations/shared/association-service", "Member[getAssociations,getAssociationsByRelation].ReturnValue.ArrayElement"] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript/associations/shared/association-service", "Member[setAssociations].Argument[1].ArrayElement"] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript/associations/shared/base-association.BaseAssociation", ""] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript", "Member[addAssociation].Argument[1]"] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript", "Member[getAssociations,getAssociationsByRelation].ReturnValue.ArrayElement"] + - ["sequelize-typescript.BaseAssociation", "sequelize-typescript", "Member[setAssociations].Argument[1].ArrayElement"] + - ["sequelize-typescript.BaseAssociationStatic", "sequelize-typescript/associations/shared/base-association.BaseAssociationStatic", ""] + - ["sequelize-typescript.BaseAssociationStatic", "sequelize-typescript/associations/shared/base-association", "Member[BaseAssociation]"] + - ["sequelize-typescript.BaseAssociationStatic", "sequelize-typescript", "Member[BaseAssociation]"] + - ["sequelize-typescript.BelongsToAssociation", "sequelize-typescript.BelongsToAssociationStatic", Instance] + - ["sequelize-typescript.BelongsToAssociation", "sequelize-typescript/associations/belongs-to/belongs-to-association.BelongsToAssociation", ""] + - ["sequelize-typescript.BelongsToAssociationStatic", "sequelize-typescript/associations/belongs-to/belongs-to-association.BelongsToAssociationStatic", ""] + - ["sequelize-typescript.BelongsToAssociationStatic", "sequelize-typescript/associations/belongs-to/belongs-to-association", "Member[BelongsToAssociation]"] + - ["sequelize-typescript.BelongsToAssociationStatic", "sequelize-typescript", "Member[BelongsToAssociation]"] + - ["sequelize-typescript.BelongsToManyAssociation", "sequelize-typescript.BelongsToManyAssociationStatic", Instance] + - ["sequelize-typescript.BelongsToManyAssociation", "sequelize-typescript/associations/belongs-to-many/belongs-to-many-association.BelongsToManyAssociation", ""] + - ["sequelize-typescript.BelongsToManyAssociationStatic", "sequelize-typescript/associations/belongs-to-many/belongs-to-many-association.BelongsToManyAssociationStatic", ""] + - ["sequelize-typescript.BelongsToManyAssociationStatic", "sequelize-typescript/associations/belongs-to-many/belongs-to-many-association", "Member[BelongsToManyAssociation]"] + - ["sequelize-typescript.BelongsToManyAssociationStatic", "sequelize-typescript", "Member[BelongsToManyAssociation]"] + - ["sequelize-typescript.DefaultScopeGetter", "sequelize-typescript.ScopeOptionsGetters", "Member[getDefaultScope]"] + - ["sequelize-typescript.DefaultScopeGetter", "sequelize-typescript/scopes/default-scope", "Member[DefaultScope].Argument[0]"] + - ["sequelize-typescript.DefaultScopeGetter", "sequelize-typescript/scopes/scope-options.DefaultScopeGetter", ""] + - ["sequelize-typescript.DefaultScopeGetter", "sequelize-typescript", "Member[DefaultScope].Argument[0]"] + - ["sequelize-typescript.HasAssociation", "sequelize-typescript.HasAssociationStatic", Instance] + - ["sequelize-typescript.HasAssociation", "sequelize-typescript/associations/has/has-association.HasAssociation", ""] + - ["sequelize-typescript.HasAssociationStatic", "sequelize-typescript/associations/has/has-association.HasAssociationStatic", ""] + - ["sequelize-typescript.HasAssociationStatic", "sequelize-typescript/associations/has/has-association", "Member[HasAssociation]"] + - ["sequelize-typescript.HasAssociationStatic", "sequelize-typescript", "Member[HasAssociation]"] + - ["sequelize-typescript.Model", "sequelize-typescript.Model", "Member[$add,$has,$remove,$set].Argument[1]"] + - ["sequelize-typescript.Model", "sequelize-typescript.Model", "Member[$add,$has,$remove,$set].Argument[1].ArrayElement"] + - ["sequelize-typescript.Model", "sequelize-typescript.Model", "Member[$create,reload].ReturnValue.Awaited"] + - ["sequelize-typescript.Model", "sequelize-typescript.ModelStatic~", Instance] + - ["sequelize-typescript.Model", "sequelize-typescript.ModelStatic~", "Member[initialize].ReturnValue.TypeVar[sequelize-typescript.ModelStatic.0]"] + - ["sequelize-typescript.Model", "sequelize-typescript.ModelType", Instance] + - ["sequelize-typescript.Model", "sequelize-typescript.Sequelize", "Member[getRepository].Argument[0].Instance"] + - ["sequelize-typescript.Model", "sequelize-typescript.Sequelize", "Member[getRepository].ReturnValue.TypeVar[sequelize-typescript.Repository.0]"] + - ["sequelize-typescript.Model", "sequelize-typescript/model/model/model.Model", ""] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript.BaseAssociationStatic", "Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript.BelongsToAssociationStatic", "Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript.BelongsToManyAssociationStatic", "Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript.HasAssociationStatic", "Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/belongs-to-many/belongs-to-many", "Member[BelongsToMany].Argument[0,1]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/belongs-to/belongs-to", "Member[BelongsTo].Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/foreign-key/foreign-key-meta.ForeignKeyMeta", "Member[relatedClassGetter]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/foreign-key/foreign-key-service", "Member[addForeignKey].Argument[1]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/foreign-key/foreign-key", "Member[ForeignKey].Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/has/has-many", "Member[HasMany].Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/associations/has/has-one", "Member[HasOne].Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript/model/shared/model-class-getter.ModelClassGetter", ""] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript", "Member[BelongsTo,ForeignKey,HasMany,HasOne].Argument[0]"] + - ["sequelize-typescript.ModelClassGetter", "sequelize-typescript", "Member[BelongsToMany].Argument[0,1]"] + - ["sequelize-typescript.ModelStatic~", "sequelize-typescript/model/model/model.ModelStatic~", ""] + - ["sequelize-typescript.ModelStatic~", "sequelize-typescript/model/model/model", "Member[Model]"] + - ["sequelize-typescript.ModelStatic~", "sequelize-typescript/model/shared/model-not-initialized-error.ModelNotInitializedErrorStatic", "Argument[0]"] + - ["sequelize-typescript.ModelStatic~", "sequelize-typescript", "Member[Model]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.BaseAssociation", "Member[getAssociatedClass].ReturnValue"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.BaseAssociation", "Member[getSequelizeOptions].Argument[0]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.BelongsToAssociation", "Member[getSequelizeOptions].Argument[0]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.BelongsToManyAssociation", "Member[getSequelizeOptions].Argument[0]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.HasAssociation", "Member[getSequelizeOptions].Argument[0]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript.ModelClassGetter", ReturnValue] + - ["sequelize-typescript.ModelType", "sequelize-typescript.Sequelize", "Member[model].Argument[0]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript/associations/foreign-key/foreign-key-service", "Member[getForeignKeyOptions].Argument[0,1]"] + - ["sequelize-typescript.ModelType", "sequelize-typescript/model/model/model.ModelType", ""] + - ["sequelize-typescript.ScopeOptionsGetters", "sequelize-typescript/scopes/scope-options.ScopeOptionsGetters", ""] + - ["sequelize-typescript.ScopeOptionsGetters", "sequelize-typescript/scopes/scope-service", "Member[addScopeOptionsGetter,setScopeOptionsGetters].Argument[1]"] + - ["sequelize-typescript.ScopeOptionsGetters", "sequelize-typescript/scopes/scope-service", "Member[getScopeOptionsGetters].ReturnValue"] + - ["sequelize-typescript.ScopeOptionsGetters", "sequelize-typescript", "Member[addScopeOptionsGetter,setScopeOptionsGetters].Argument[1]"] + - ["sequelize-typescript.ScopeOptionsGetters", "sequelize-typescript", "Member[getScopeOptionsGetters].ReturnValue"] + - ["sequelize-typescript.ScopesOptions", "sequelize-typescript.ScopesOptionsGetter", ReturnValue.AnyMember] + - ["sequelize-typescript.ScopesOptions", "sequelize-typescript/scopes/scope-options.ScopesOptions", ""] + - ["sequelize-typescript.ScopesOptions", "sequelize-typescript/scopes/scope-service", "Member[resolveScope].Argument[2]"] + - ["sequelize-typescript.ScopesOptions", "sequelize-typescript", "Member[resolveScope].Argument[2]"] + - ["sequelize-typescript.ScopesOptionsGetter", "sequelize-typescript.ScopeOptionsGetters", "Member[getScopes]"] + - ["sequelize-typescript.ScopesOptionsGetter", "sequelize-typescript/scopes/scope-options.ScopesOptionsGetter", ""] + - ["sequelize-typescript.ScopesOptionsGetter", "sequelize-typescript/scopes/scopes", "Member[Scopes].Argument[0]"] + - ["sequelize-typescript.ScopesOptionsGetter", "sequelize-typescript", "Member[Scopes].Argument[0]"] + - ["sequelize-typescript.Sequelize", "sequelize-typescript.BaseAssociation", "Member[getSequelizeOptions].Argument[1]"] + - ["sequelize-typescript.Sequelize", "sequelize-typescript.BelongsToManyAssociation", "Member[getSequelizeOptions].Argument[1]"] + - ["sequelize-typescript.Sequelize", "sequelize-typescript.SequelizeStatic", Instance] + - ["sequelize-typescript.Sequelize", "sequelize-typescript/sequelize/sequelize/sequelize.Sequelize", ""] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.Sequelize", "Member[options]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.SequelizeStatic", "Argument[3]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.SequelizeStatic", "WithArity[0].Argument[0]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.SequelizeStatic", "WithArity[1].Argument[0,1]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.SequelizeStatic", "WithArity[2].Argument[1,2]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript.SequelizeStatic", "WithArity[3].Argument[2]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript/sequelize/sequelize/sequelize-options.SequelizeOptions", ""] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript/sequelize/sequelize/sequelize-service", "Member[prepareArgs].ReturnValue.Member[options]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript/sequelize/sequelize/sequelize-service", "Member[prepareOptions].Argument[0]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript/sequelize/sequelize/sequelize-service", "Member[prepareOptions].ReturnValue"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript", "Member[prepareArgs].ReturnValue.Member[options]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript", "Member[prepareOptions].Argument[0]"] + - ["sequelize-typescript.SequelizeOptions", "sequelize-typescript", "Member[prepareOptions].ReturnValue"] + - ["sequelize-typescript.SequelizeStatic", "sequelize-typescript/sequelize/sequelize/sequelize.SequelizeStatic", ""] + - ["sequelize-typescript.SequelizeStatic", "sequelize-typescript/sequelize/sequelize/sequelize", "Member[Sequelize]"] + - ["sequelize-typescript.SequelizeStatic", "sequelize-typescript", "Member[Sequelize]"] + - ["sequelize-typescript/associations/foreign-key/foreign-key-meta.ForeignKeyMeta", "sequelize-typescript/associations/foreign-key/foreign-key-service", "Member[getForeignKeys].ReturnValue.ArrayElement"] + - ["sequelize-typescript/model/model/association/association-create-options.AssociationCreateOptions", "sequelize-typescript.Model", "Member[$create].Argument[2]"] + - ["sequelize-typescript/model/shared/model-not-initialized-error.ModelNotInitializedErrorStatic", "sequelize-typescript/model/shared/model-not-initialized-error", "Member[ModelNotInitializedError]"] + - [sequelize.AnyFindOptions, sequelize.BelongsToManyAddAssociationMixin, "Argument[1]"] + - [sequelize.AnyFindOptions, sequelize.BelongsToManyAddAssociationsMixin, "Argument[1]"] + - [sequelize.AnyFindOptions, sequelize.BelongsToManySetAssociationsMixin, "Argument[1]"] + - [sequelize.AnyFindOptions, sequelize.DefineOptions, "Member[defaultScope]"] + - [sequelize.AnyFindOptions, sequelize.DefineScopeOptions, AnyMember] + - [sequelize.AnyFindOptions, sequelize.HasManySetAssociationsMixin, "Argument[1]"] + - [sequelize.AnyFindOptions, sequelize.Instance, "Member[reload].Argument[0]"] + - [sequelize.AnyFindOptions, sequelize.Model, "Member[addScope].Argument[1]"] + - [sequelize.AssociationOptionsBelongsToMany, sequelize.Associations, "Member[belongsToMany].Argument[1]"] + - [sequelize.Associations, sequelize.Model, ""] + - [sequelize.Associations, sequelize.SequelizeStaticAndInstance.Model, ""] + - [sequelize.BuildOptions, "sequelize-typescript.ModelStatic~", "Argument[1]"] + - [sequelize.BuildOptions, sequelize.CreateOptions, ""] + - [sequelize.BuildOptions, sequelize.Model, "Member[build,bulkBuild].Argument[1]"] + - [sequelize.CountOptions, sequelize.Model, "Member[count].Argument[0]"] + - [sequelize.CreateOptions, "sequelize-typescript/model/model/association/association-create-options.AssociationCreateOptions", ""] + - [sequelize.CreateOptions, sequelize.BelongsToCreateAssociationMixin, "Argument[1]"] + - [sequelize.CreateOptions, sequelize.BelongsToManyCreateAssociationMixin, "Argument[1]"] + - [sequelize.CreateOptions, sequelize.HasManyCreateAssociationMixin, "Argument[1]"] + - [sequelize.CreateOptions, sequelize.HasOneCreateAssociationMixin, "Argument[1]"] + - [sequelize.CreateOptions, sequelize.Model, "Member[create].Argument[1]"] + - [sequelize.DefineAttributeColumnOptions, sequelize.DefineAttributes, AnyMember] + - [sequelize.DefineAttributeColumnOptions, sequelize.QueryInterface, "Member[addColumn,changeColumn].Argument[2]"] + - [sequelize.DefineAttributeColumnReferencesOptions, sequelize.DefineAttributeColumnOptions, "Member[references]"] + - [sequelize.DefineAttributes, sequelize.Hooks, "Member[beforeDefine].Argument[1].Argument[0]"] + - [sequelize.DefineAttributes, sequelize.Hooks, "Member[beforeDefine].WithArity[1].Argument[0].Argument[0]"] + - [sequelize.DefineAttributes, sequelize.QueryInterface, "Member[createTable].Argument[1]"] + - [sequelize.DefineOptions, sequelize.Options, "Member[define]"] + - [sequelize.DefineOptions, sequelize.Sequelize, "Member[define].Argument[2]"] + - [sequelize.DefineScopeOptions, sequelize.DefineOptions, "Member[scopes]"] + - [sequelize.FindCreateFindOptions, sequelize.Model, "Member[findCreateFind].Argument[0]"] + - [sequelize.FindOptions, "sequelize-typescript.AssociationCountOptions", ""] + - [sequelize.FindOptions, "sequelize-typescript.AssociationGetOptions", ""] + - [sequelize.FindOptions, "sequelize-typescript.DefaultScopeGetter", ReturnValue] + - [sequelize.FindOptions, "sequelize-typescript.Model", "Member[reload].Argument[0]"] + - [sequelize.FindOptions, "sequelize-typescript.ScopesOptions", ""] + - [sequelize.FindOptions, "sequelize-typescript.ScopesOptions", ReturnValue] + - [sequelize.FindOptions, sequelize.AnyFindOptions, ""] + - [sequelize.FindOptions, sequelize.FindCreateFindOptions, ""] + - [sequelize.FindOptions, sequelize.FindOrInitializeOptions, ""] + - [sequelize.FindOptions, sequelize.Model, "Member[all,find,findAll,findAndCount,findAndCountAll,findOne].Argument[0]"] + - [sequelize.FindOptionsOrderArray, sequelize.FindOptions, "Member[order]"] + - [sequelize.FindOptionsOrderArray, sequelize.FindOptions, "Member[order].ArrayElement"] + - [sequelize.FindOrInitializeOptions, sequelize.Model, "Member[findOrBuild,findOrCreate,findOrInitialize].Argument[0]"] + - [sequelize.HasManyGetAssociationsMixinOptions, sequelize.HasManyGetAssociationsMixin, "Argument[0]"] + - [sequelize.HasManyGetAssociationsMixinOptions, sequelize.HasManyHasAssociationMixin, "Argument[1]"] + - [sequelize.HasManyGetAssociationsMixinOptions, sequelize.HasManyHasAssociationsMixin, "Argument[1]"] + - [sequelize.Hooks, sequelize.Hooks, "Member[addHook,hook,removeHook].ReturnValue"] + - [sequelize.Hooks, sequelize.Model, ""] + - [sequelize.Hooks, sequelize.Sequelize, ""] + - [sequelize.Hooks, sequelize.SequelizeStaticAndInstance.Model, ""] + - [sequelize.IncludeAssociation, sequelize.Associations, "Member[belongsTo,belongsToMany,hasMany,hasOne].ReturnValue"] + - [sequelize.IncludeAssociation, sequelize.IncludeOptions, "Member[association]"] + - [sequelize.IncludeOptions, sequelize.BuildOptions, "Member[include].ArrayElement"] + - [sequelize.IncludeOptions, sequelize.CountOptions, "Member[include]"] + - [sequelize.IncludeOptions, sequelize.CountOptions, "Member[include].ArrayElement"] + - [sequelize.IncludeOptions, sequelize.FindOptions, "Member[include]"] + - [sequelize.IncludeOptions, sequelize.FindOptions, "Member[include].ArrayElement"] + - [sequelize.IncludeOptions, sequelize.HasManyGetAssociationsMixinOptions, "Member[include]"] + - [sequelize.IncludeOptions, sequelize.IncludeOptions, "Member[include]"] + - [sequelize.IncludeOptions, sequelize.IncludeOptions, "Member[include].ArrayElement"] + - [sequelize.Instance, sequelize.Instance, "Member[decrement,increment,reload,save,update,updateAttributes].ReturnValue.Awaited"] + - [sequelize.Instance, sequelize.Instance, "Member[equalsOneOf].Argument[0].ArrayElement"] + - [sequelize.Instance, sequelize.Instance, "Member[equals].Argument[0]"] + - [sequelize.Instance, sequelize.Instance, "Member[set,setAttributes].ReturnValue"] + - [sequelize.Instance, sequelize.Model, "Member[Instance,build].ReturnValue"] + - [sequelize.Instance, sequelize.Model, "Member[all,bulkCreate,findAll].ReturnValue.Awaited.ArrayElement"] + - [sequelize.Instance, sequelize.Model, "Member[bulkBuild].ReturnValue.ArrayElement"] + - [sequelize.Instance, sequelize.Model, "Member[create,find,findById,findByPk,findByPrimary,findOne].ReturnValue.Awaited"] + - [sequelize.Instance, sequelize.Model, "Member[findAndCount,findAndCountAll].ReturnValue.Awaited.Member[rows].ArrayElement"] + - [sequelize.Instance, sequelize.QueryInterface, "Member[delete,increment,insert,update].Argument[0]"] + - [sequelize.Instance, sequelize.QueryOptions, "Member[instance]"] + - [sequelize.Instance, sequelize.SequelizeStaticAndInstance, "Member[Instance]"] + - [sequelize.Model, sequelize.AssociationOptionsBelongsToMany, "Member[through]"] + - [sequelize.Model, sequelize.Associations, "Member[belongsTo,belongsToMany,hasMany,hasOne].Argument[0]"] + - [sequelize.Model, sequelize.BuildOptions, "Member[include].ArrayElement"] + - [sequelize.Model, sequelize.CountOptions, "Member[include]"] + - [sequelize.Model, sequelize.CountOptions, "Member[include].ArrayElement"] + - [sequelize.Model, sequelize.DefineAttributeColumnReferencesOptions, "Member[model]"] + - [sequelize.Model, sequelize.FindOptions, "Member[include]"] + - [sequelize.Model, sequelize.FindOptions, "Member[include].ArrayElement"] + - [sequelize.Model, sequelize.FindOptions, "Member[lock].Member[of]"] + - [sequelize.Model, sequelize.FindOptionsOrderArray, ArrayElement] + - [sequelize.Model, sequelize.FindOptionsOrderArray, "ArrayElement.Member[model]"] + - [sequelize.Model, sequelize.Hooks, "Member[afterDefine].Argument[1].Argument[0]"] + - [sequelize.Model, sequelize.Hooks, "Member[afterDefine].WithArity[1].Argument[0].Argument[0]"] + - [sequelize.Model, sequelize.IncludeAssociation, "Member[source,target]"] + - [sequelize.Model, sequelize.IncludeOptions, "Member[include,model]"] + - [sequelize.Model, sequelize.IncludeOptions, "Member[include].ArrayElement"] + - [sequelize.Model, sequelize.Instance, "Member[Model]"] + - [sequelize.Model, sequelize.Model, "Member[schema,scope,unscoped].ReturnValue"] + - [sequelize.Model, sequelize.Model, "Member[sync].ReturnValue.Awaited"] + - [sequelize.Model, sequelize.Models, AnyMember] + - [sequelize.Model, sequelize.ModelsHashInterface, AnyMember] + - [sequelize.Model, sequelize.QueryInterface, "Member[bulkDelete,rawSelect,upsert].Argument[3]"] + - [sequelize.Model, sequelize.QueryInterface, "Member[select].Argument[0]"] + - [sequelize.Model, sequelize.QueryOptions, "Member[model]"] + - [sequelize.Model, sequelize.Sequelize, "Member[define,import,model].ReturnValue"] + - [sequelize.Model, sequelize.Sequelize, "Member[import].Argument[1].ReturnValue"] + - [sequelize.Model, sequelize.SequelizeStaticAndInstance, "Member[Model]"] + - [sequelize.Model, sequelize.ThroughOptions, "Member[model]"] + - [sequelize.Model, sequelize.Utils, "Member[mapOptionFieldNames].Argument[1]"] + - [sequelize.Model, sequelize.Utils, "Member[mapValueFieldNames].Argument[2]"] + - [sequelize.Models, sequelize.Model, "Member[associate].Argument[0]"] + - [sequelize.ModelsHashInterface, sequelize.Sequelize, "Member[models]"] + - [sequelize.Options, "sequelize-typescript.SequelizeOptions", ""] + - [sequelize.Options, sequelize.Sequelize, "Member[options]"] + - [sequelize.Options, sequelize.SequelizeStatic, "Argument[3]"] + - [sequelize.Options, sequelize.SequelizeStatic, "WithArity[1].Argument[0,1]"] + - [sequelize.Options, sequelize.SequelizeStatic, "WithArity[2].Argument[1,2]"] + - [sequelize.Options, sequelize.SequelizeStatic, "WithArity[3].Argument[2]"] + - [sequelize.QueryInterface, sequelize.Sequelize, "Member[getQueryInterface].ReturnValue"] + - [sequelize.QueryOptions, sequelize.Options, "Member[query]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[bulkDelete,bulkInsert,createTable,select,setAutocommit,setIsolationLevel].Argument[2]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[bulkUpdate,delete,insert].Argument[3]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[commitTransaction,deferConstraints,dropTable,rawSelect,rollbackTransaction,showIndex,startTransaction].Argument[1]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[createFunction].Argument[5]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[dropAllEnums,dropAllTables,showAllSchemas,showAllTables].Argument[0]"] + - [sequelize.QueryOptions, sequelize.QueryInterface, "Member[increment,update,upsert].Argument[4]"] + - [sequelize.QueryOptions, sequelize.Sequelize, "Member[authenticate,validate].Argument[0]"] + - [sequelize.QueryOptions, sequelize.Sequelize, "Member[query].Argument[1]"] + - [sequelize.Sequelize, "sequelize-typescript.Sequelize", ""] + - [sequelize.Sequelize, sequelize.Hooks, "Member[afterInit].Argument[1].Argument[0]"] + - [sequelize.Sequelize, sequelize.Hooks, "Member[afterInit].WithArity[1].Argument[0].Argument[0]"] + - [sequelize.Sequelize, sequelize.Instance, "Member[sequelize]"] + - [sequelize.Sequelize, sequelize.QueryInterface, "Member[sequelize]"] + - [sequelize.Sequelize, sequelize.Sequelize, "Member[import].Argument[1].Argument[0]"] + - [sequelize.Sequelize, sequelize.SequelizeStatic, Instance] + - [sequelize.Sequelize, sequelize.SequelizeStatic, "Member[useCLS].ReturnValue"] + - [sequelize.SequelizeStatic, "sequelize-typescript.Sequelize", ""] + - [sequelize.SequelizeStatic, sequelize.Sequelize, "Member[Sequelize]"] + - [sequelize.SequelizeStatic, sequelize.SequelizeStatic, "Member[Sequelize,default]"] + - [sequelize.SequelizeStatic, sequelize, ""] + - [sequelize.SequelizeStaticAndInstance.Model, "sequelize-typescript.Model", ""] + - [sequelize.SequelizeStaticAndInstance, sequelize.Sequelize, ""] + - [sequelize.SequelizeStaticAndInstance, sequelize.SequelizeStatic, ""] + - [sequelize.ThroughOptions, sequelize.AssociationOptionsBelongsToMany, "Member[through]"] + - [sequelize.Utils, sequelize.SequelizeStaticAndInstance, "Member[Utils]"] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - ["sequelize-typescript.Model", "", "", "Member[reload].ReturnValue.Awaited", type] + - [sequelize.Instance, "", "", "Member[decrement,increment,reload,save,update,updateAttributes].ReturnValue.Awaited", type] + - [sequelize.Instance, "", "", "Member[set,setAttributes].ReturnValue", type] + - [sequelize.Model, "", "", "Member[schema,scope,unscoped].ReturnValue", type] + - [sequelize.Model, "", "", "Member[sync].ReturnValue.Awaited", type] + + - addsTo: + pack: codeql/javascript-all + extensible: typeVariableModel + data: + - ["sequelize-typescript.ModelStatic.0", Instance] + - ["sequelize-typescript.Repository.0", Instance] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/spanner/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/spanner/Model.qll deleted file mode 100644 index 630fa5ea8c9..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/spanner/Model.qll +++ /dev/null @@ -1,198 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "@google-cloud/spanner.BackupStatic;@google-cloud/spanner/backup.BackupStatic;", // - "@google-cloud/spanner.BackupStatic;@google-cloud/spanner/backup;Member[Backup]", // - "@google-cloud/spanner.BackupStatic;@google-cloud/spanner;Member[Backup]", // - "@google-cloud/spanner.BatchTransaction;@google-cloud/spanner/batch-transaction.BatchTransaction;", // - "@google-cloud/spanner.Database;@google-cloud/spanner.DatabaseStatic;Instance", // - "@google-cloud/spanner.Database;@google-cloud/spanner.Instance;Member[database].ReturnValue", // - "@google-cloud/spanner.Database;@google-cloud/spanner.SessionPool;Member[database]", // - "@google-cloud/spanner.Database;@google-cloud/spanner.SessionPoolStatic;Argument[0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner.SessionStatic;Argument[0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner.Table;Member[database]", // - "@google-cloud/spanner.Database;@google-cloud/spanner.TableStatic;Argument[0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner/database.Database;", // - "@google-cloud/spanner.Database;@google-cloud/spanner/database.DatabaseCallback;TypeVar[@google-cloud/spanner/common.ResourceCallback.0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner/database.RestoreDatabaseCallback;TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner/database.SessionPoolConstructor;Argument[0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner/instance.CreateDatabaseCallback;TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]", // - "@google-cloud/spanner.Database;@google-cloud/spanner/instance.GetDatabasesCallback;TypeVar[@google-cloud/spanner/common.RequestCallback.0]", // - "@google-cloud/spanner.DatabaseStatic;@google-cloud/spanner/database.DatabaseStatic;", // - "@google-cloud/spanner.DatabaseStatic;@google-cloud/spanner/database;Member[Database]", // - "@google-cloud/spanner.DatabaseStatic;@google-cloud/spanner;Member[Database]", // - "@google-cloud/spanner.GetInstancesCallback;@google-cloud/spanner.Spanner;Member[getInstances].Argument[1]", // - "@google-cloud/spanner.GetInstancesCallback;@google-cloud/spanner.Spanner;Member[getInstances].WithArity[1].Argument[0]", // - "@google-cloud/spanner.GetInstancesCallback;@google-cloud/spanner/build/src.GetInstancesCallback;", // - "@google-cloud/spanner.Instance;@google-cloud/spanner.BackupStatic;Argument[0]", // - "@google-cloud/spanner.Instance;@google-cloud/spanner.DatabaseStatic;Argument[0]", // - "@google-cloud/spanner.Instance;@google-cloud/spanner.GetInstancesCallback;TypeVar[@google-cloud/spanner/common.PagedCallback.0]", // - "@google-cloud/spanner.Instance;@google-cloud/spanner.InstanceStatic;Instance", // - "@google-cloud/spanner.Instance;@google-cloud/spanner.Spanner;Member[instance].ReturnValue", // - "@google-cloud/spanner.Instance;@google-cloud/spanner/instance.CreateInstanceCallback;TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]", // - "@google-cloud/spanner.Instance;@google-cloud/spanner/instance.GetInstanceCallback;TypeVar[@google-cloud/spanner/common.ResourceCallback.0]", // - "@google-cloud/spanner.Instance;@google-cloud/spanner/instance.Instance;", // - "@google-cloud/spanner.InstanceStatic;@google-cloud/spanner/instance.InstanceStatic;", // - "@google-cloud/spanner.InstanceStatic;@google-cloud/spanner/instance;Member[Instance]", // - "@google-cloud/spanner.InstanceStatic;@google-cloud/spanner;Member[Instance]", // - "@google-cloud/spanner.PartitionedDml;@google-cloud/spanner.PartitionedDmlStatic;Instance", // - "@google-cloud/spanner.PartitionedDml;@google-cloud/spanner.Session;Member[partitionedDml].ReturnValue", // - "@google-cloud/spanner.PartitionedDml;@google-cloud/spanner/transaction.PartitionedDml;", // - "@google-cloud/spanner.PartitionedDmlStatic;@google-cloud/spanner/transaction.PartitionedDmlStatic;", // - "@google-cloud/spanner.PartitionedDmlStatic;@google-cloud/spanner/transaction;Member[PartitionedDml]", // - "@google-cloud/spanner.PartitionedDmlStatic;@google-cloud/spanner;Member[PartitionedDml]", // - "@google-cloud/spanner.Session;@google-cloud/spanner.Database;Member[_runPartitionedUpdate].Argument[0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner.Database;Member[makePooledRequest_].WithArity[1].ReturnValue.Awaited", // - "@google-cloud/spanner.Session;@google-cloud/spanner.Database;Member[session].ReturnValue", // - "@google-cloud/spanner.Session;@google-cloud/spanner.SessionPool;Member[_acquire,_getSession].ReturnValue.Awaited", // - "@google-cloud/spanner.Session;@google-cloud/spanner.SessionPool;Member[_borrow,_destroy,_isValidSession,_ping,_prepareTransaction,_release,release].Argument[0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner.SessionPool;Member[_borrowFrom,_borrowNextAvailableSession].ReturnValue", // - "@google-cloud/spanner.Session;@google-cloud/spanner.SessionPool;Member[_getIdleSessions].ReturnValue.ArrayElement", // - "@google-cloud/spanner.Session;@google-cloud/spanner.SessionStatic;Instance", // - "@google-cloud/spanner.Session;@google-cloud/spanner.Snapshot;Member[session]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/batch-transaction.TransactionIdentifier;Member[session]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/database.BatchCreateSessionsCallback;TypeVar[@google-cloud/spanner/common.ResourceCallback.0].ArrayElement", // - "@google-cloud/spanner.Session;@google-cloud/spanner/database.CreateSessionCallback;TypeVar[@google-cloud/spanner/common.ResourceCallback.0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/database.GetSessionsCallback;TypeVar[@google-cloud/spanner/common.RequestCallback.0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/database.PoolRequestCallback;TypeVar[@google-cloud/spanner/common.RequestCallback.0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/session-pool.GetReadSessionCallback;TypeVar[@google-cloud/spanner/common.NormalCallback.0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/session-pool.GetWriteSessionCallback;Argument[1]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/session-pool.SessionPoolInterface;Member[release].Argument[0]", // - "@google-cloud/spanner.Session;@google-cloud/spanner/session.Session;", // - "@google-cloud/spanner.Session;@google-cloud/spanner/transaction-runner.Runner;Member[session]", // - "@google-cloud/spanner.SessionPool;@google-cloud/spanner.SessionPoolStatic;Instance", // - "@google-cloud/spanner.SessionPool;@google-cloud/spanner/instance.CreateDatabaseOptions;Member[poolCtor]", // - "@google-cloud/spanner.SessionPool;@google-cloud/spanner/session-pool.SessionPool;", // - "@google-cloud/spanner.SessionPoolStatic;@google-cloud/spanner/session-pool.SessionPoolStatic;", // - "@google-cloud/spanner.SessionPoolStatic;@google-cloud/spanner/session-pool;Member[SessionPool]", // - "@google-cloud/spanner.SessionPoolStatic;@google-cloud/spanner;Member[SessionPool]", // - "@google-cloud/spanner.SessionStatic;@google-cloud/spanner/session.SessionStatic;", // - "@google-cloud/spanner.SessionStatic;@google-cloud/spanner/session;Member[Session]", // - "@google-cloud/spanner.SessionStatic;@google-cloud/spanner;Member[Session]", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner.Session;Member[snapshot].ReturnValue", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner.SnapshotStatic;Instance", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner/batch-transaction.BatchTransaction;", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner/database.GetSnapshotCallback;TypeVar[@google-cloud/spanner/common.NormalCallback.0]", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner/transaction.Dml;", // - "@google-cloud/spanner.Snapshot;@google-cloud/spanner/transaction.Snapshot;", // - "@google-cloud/spanner.SnapshotStatic;@google-cloud/spanner/transaction.SnapshotStatic;", // - "@google-cloud/spanner.SnapshotStatic;@google-cloud/spanner/transaction;Member[Snapshot]", // - "@google-cloud/spanner.SnapshotStatic;@google-cloud/spanner;Member[Snapshot]", // - "@google-cloud/spanner.Spanner;@google-cloud/spanner.InstanceStatic;Argument[0]", // - "@google-cloud/spanner.Spanner;@google-cloud/spanner.SpannerStatic;Instance", // - "@google-cloud/spanner.SpannerStatic;@google-cloud/spanner;Member[Spanner]", // - "@google-cloud/spanner.Table;@google-cloud/spanner.Database;Member[table].ReturnValue", // - "@google-cloud/spanner.Table;@google-cloud/spanner.TableStatic;Instance", // - "@google-cloud/spanner.Table;@google-cloud/spanner/table.CreateTableCallback;TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]", // - "@google-cloud/spanner.Table;@google-cloud/spanner/table.Table;", // - "@google-cloud/spanner.TableStatic;@google-cloud/spanner/table.TableStatic;", // - "@google-cloud/spanner.TableStatic;@google-cloud/spanner/table;Member[Table]", // - "@google-cloud/spanner.TableStatic;@google-cloud/spanner;Member[Table]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner.Session;Member[transaction].ReturnValue", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner.Session;Member[txn]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner.TransactionStatic;Instance", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/database.GetTransactionCallback;TypeVar[@google-cloud/spanner/common.NormalCallback.0]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/session-pool.GetWriteSessionCallback;Argument[2]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback;Argument[0]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/transaction-runner.RunTransactionCallback;TypeVar[@google-cloud/spanner/common.NormalCallback.0]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/transaction-runner.Runner;Member[getTransaction].ReturnValue.Awaited", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/transaction-runner.Runner;Member[transaction]", // - "@google-cloud/spanner.Transaction;@google-cloud/spanner/transaction.Transaction;", // - "@google-cloud/spanner.TransactionStatic;@google-cloud/spanner/transaction.TransactionStatic;", // - "@google-cloud/spanner.TransactionStatic;@google-cloud/spanner/transaction;Member[Transaction]", // - "@google-cloud/spanner.TransactionStatic;@google-cloud/spanner;Member[Transaction]", // - "@google-cloud/spanner.v1.SpannerClient;@google-cloud/spanner.v1.SpannerClientStatic;Instance", // - "@google-cloud/spanner.v1.SpannerClient;@google-cloud/spanner/v1/spanner_client.SpannerClient;", // - "@google-cloud/spanner.v1.SpannerClientStatic;@google-cloud/spanner/v1/spanner_client.SpannerClientStatic;", // - "@google-cloud/spanner.v1.SpannerClientStatic;@google-cloud/spanner/v1/spanner_client;Member[SpannerClient]", // - "@google-cloud/spanner.v1.SpannerClientStatic;@google-cloud/spanner;Member[v1].Member[SpannerClient]", // - "@google-cloud/spanner.~SpannerObject;@google-cloud/spanner.Database;", // - "@google-cloud/spanner.~SpannerObject;@google-cloud/spanner.Snapshot;", // - "@google-cloud/spanner.~SpannerObject;@google-cloud/spanner.Transaction;", // - "@google-cloud/spanner.~SpannerObject;@google-cloud/spanner.v1.SpannerClient;", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.BatchTransaction;Member[createQueryPartitions]", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.Database;Member[run,runPartitionedUpdate,runStream]", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.PartitionedDml;Member[runUpdate]", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.Snapshot;Member[run,runStream]", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.Transaction;Member[run,runStream,runUpdate]", // - "@google-cloud/spanner.~SqlExecutorDirect;@google-cloud/spanner.v1.SpannerClient;Member[executeSql,executeStreamingSql,partitionQuery]", // - "@google-cloud/spanner/batch-transaction.BatchTransaction;@google-cloud/spanner.Database;Member[batchTransaction].ReturnValue", // - "@google-cloud/spanner/batch-transaction.BatchTransaction;@google-cloud/spanner/batch-transaction.BatchTransactionStatic;Instance", // - "@google-cloud/spanner/batch-transaction.BatchTransaction;@google-cloud/spanner/database.CreateBatchTransactionCallback;TypeVar[@google-cloud/spanner/common.ResourceCallback.0]", // - "@google-cloud/spanner/batch-transaction.BatchTransactionStatic;@google-cloud/spanner/batch-transaction;Member[BatchTransaction]", // - "@google-cloud/spanner/batch-transaction.TransactionIdentifier;@google-cloud/spanner.Database;Member[batchTransaction].Argument[0]", // - "@google-cloud/spanner/batch-transaction.TransactionIdentifier;@google-cloud/spanner/batch-transaction.BatchTransaction;Member[identifier].ReturnValue", // - "@google-cloud/spanner/database.BatchCreateSessionsCallback;@google-cloud/spanner.Database;Member[batchCreateSessions].Argument[1]", // - "@google-cloud/spanner/database.CreateBatchTransactionCallback;@google-cloud/spanner.Database;Member[createBatchTransaction].Argument[1]", // - "@google-cloud/spanner/database.CreateBatchTransactionCallback;@google-cloud/spanner.Database;Member[createBatchTransaction].WithArity[1].Argument[0]", // - "@google-cloud/spanner/database.CreateSessionCallback;@google-cloud/spanner.Database;Member[createSession].Argument[1]", // - "@google-cloud/spanner/database.CreateSessionCallback;@google-cloud/spanner.Database;Member[createSession].WithArity[1].Argument[0]", // - "@google-cloud/spanner/database.DatabaseCallback;@google-cloud/spanner.Database;Member[get].Argument[1]", // - "@google-cloud/spanner/database.DatabaseCallback;@google-cloud/spanner.Database;Member[get].WithArity[1].Argument[0]", // - "@google-cloud/spanner/database.GetSessionsCallback;@google-cloud/spanner.Database;Member[getSessions].Argument[1]", // - "@google-cloud/spanner/database.GetSessionsCallback;@google-cloud/spanner.Database;Member[getSessions].WithArity[1].Argument[0]", // - "@google-cloud/spanner/database.GetSnapshotCallback;@google-cloud/spanner.Database;Member[getSnapshot].Argument[1]", // - "@google-cloud/spanner/database.GetSnapshotCallback;@google-cloud/spanner.Database;Member[getSnapshot].WithArity[1].Argument[0]", // - "@google-cloud/spanner/database.GetTransactionCallback;@google-cloud/spanner.Database;Member[getTransaction].Argument[0]", // - "@google-cloud/spanner/database.PoolRequestCallback;@google-cloud/spanner.Database;Member[makePooledRequest_].Argument[1]", // - "@google-cloud/spanner/database.RestoreDatabaseCallback;@google-cloud/spanner.Database;Member[restore].Argument[1,2]", // - "@google-cloud/spanner/database.SessionPoolConstructor;@google-cloud/spanner.DatabaseStatic;Argument[2]", // - "@google-cloud/spanner/database.SessionPoolConstructor;@google-cloud/spanner.Instance;Member[database].Argument[1]", // - "@google-cloud/spanner/instance.CreateDatabaseCallback;@google-cloud/spanner.Instance;Member[createDatabase].Argument[2]", // - "@google-cloud/spanner/instance.CreateDatabaseCallback;@google-cloud/spanner.Instance;Member[createDatabase].WithArity[2].Argument[1]", // - "@google-cloud/spanner/instance.CreateDatabaseOptions;@google-cloud/spanner.Instance;Member[createDatabase].WithArity[1,2,3].Argument[1]", // - "@google-cloud/spanner/instance.CreateInstanceCallback;@google-cloud/spanner.Spanner;Member[createInstance].Argument[2]", // - "@google-cloud/spanner/instance.GetDatabasesCallback;@google-cloud/spanner.Instance;Member[getDatabases].Argument[1]", // - "@google-cloud/spanner/instance.GetDatabasesCallback;@google-cloud/spanner.Instance;Member[getDatabases].WithArity[1].Argument[0]", // - "@google-cloud/spanner/instance.GetInstanceCallback;@google-cloud/spanner.Instance;Member[get].Argument[1]", // - "@google-cloud/spanner/instance.GetInstanceCallback;@google-cloud/spanner.Instance;Member[get].WithArity[1].Argument[0]", // - "@google-cloud/spanner/session-pool.GetReadSessionCallback;@google-cloud/spanner.SessionPool;Member[getReadSession].Argument[0]", // - "@google-cloud/spanner/session-pool.GetReadSessionCallback;@google-cloud/spanner/session-pool.SessionPoolInterface;Member[getReadSession].Argument[0]", // - "@google-cloud/spanner/session-pool.GetWriteSessionCallback;@google-cloud/spanner.SessionPool;Member[getWriteSession].Argument[0]", // - "@google-cloud/spanner/session-pool.GetWriteSessionCallback;@google-cloud/spanner/session-pool.SessionPoolInterface;Member[getWriteSession].Argument[0]", // - "@google-cloud/spanner/session-pool.SessionPoolInterface;@google-cloud/spanner.Database;Member[pool_]", // - "@google-cloud/spanner/session-pool.SessionPoolInterface;@google-cloud/spanner.SessionPool;", // - "@google-cloud/spanner/session-pool.SessionPoolInterface;@google-cloud/spanner/database.SessionPoolConstructor;Instance", // - "@google-cloud/spanner/table.CreateTableCallback;@google-cloud/spanner.Database;Member[createTable].Argument[2]", // - "@google-cloud/spanner/table.CreateTableCallback;@google-cloud/spanner.Database;Member[createTable].WithArity[2].Argument[1]", // - "@google-cloud/spanner/table.CreateTableCallback;@google-cloud/spanner.Table;Member[create].Argument[2]", // - "@google-cloud/spanner/table.CreateTableCallback;@google-cloud/spanner.Table;Member[create].WithArity[2].Argument[1]", // - "@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback;@google-cloud/spanner.Database;Member[runTransactionAsync].Argument[1]", // - "@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback;@google-cloud/spanner.Database;Member[runTransactionAsync].WithArity[1].Argument[0]", // - "@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback;@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic;Argument[2]", // - "@google-cloud/spanner/transaction-runner.AsyncTransactionRunner;@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic;Instance", // - "@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic;@google-cloud/spanner/transaction-runner;Member[AsyncTransactionRunner]", // - "@google-cloud/spanner/transaction-runner.RunTransactionCallback;@google-cloud/spanner.Database;Member[runTransaction].Argument[1]", // - "@google-cloud/spanner/transaction-runner.RunTransactionCallback;@google-cloud/spanner.Database;Member[runTransaction].WithArity[1].Argument[0]", // - "@google-cloud/spanner/transaction-runner.RunTransactionCallback;@google-cloud/spanner/transaction-runner.TransactionRunnerStatic;Argument[2]", // - "@google-cloud/spanner/transaction-runner.Runner;@google-cloud/spanner/transaction-runner.AsyncTransactionRunner;", // - "@google-cloud/spanner/transaction-runner.Runner;@google-cloud/spanner/transaction-runner.RunnerStatic;Instance", // - "@google-cloud/spanner/transaction-runner.Runner;@google-cloud/spanner/transaction-runner.TransactionRunner;", // - "@google-cloud/spanner/transaction-runner.RunnerStatic;@google-cloud/spanner/transaction-runner;Member[Runner]", // - "@google-cloud/spanner/transaction-runner.TransactionRunner;@google-cloud/spanner/transaction-runner.TransactionRunnerStatic;Instance", // - "@google-cloud/spanner/transaction-runner.TransactionRunnerStatic;@google-cloud/spanner/transaction-runner;Member[TransactionRunner]", // - "@google-cloud/spanner/transaction.Dml;@google-cloud/spanner.PartitionedDml;", // - "@google-cloud/spanner/transaction.Dml;@google-cloud/spanner.Transaction;", // - "@google-cloud/spanner/transaction.Dml;@google-cloud/spanner/transaction.DmlStatic;Instance", // - "@google-cloud/spanner/transaction.DmlStatic;@google-cloud/spanner/transaction;Member[Dml]", // - ] - } -} - -private class TypeVariables extends ModelInput::TypeVariableModelCsv { - override predicate row(string row) { - row = - [ - "@google-cloud/spanner/common.LongRunningCallback.0;Argument[1]", // - "@google-cloud/spanner/common.NormalCallback.0;Argument[1]", // - "@google-cloud/spanner/common.PagedCallback.0;Argument[1].ArrayElement", // - "@google-cloud/spanner/common.RequestCallback.0;TypeVar[@google-cloud/spanner/common.NormalCallback.0,@google-cloud/spanner/common.PagedCallback.0]", // - "@google-cloud/spanner/common.ResourceCallback.0;Argument[1]", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/spanner/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/spanner/model.yml new file mode 100644 index 00000000000..bf6e3fa4e5a --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/spanner/model.yml @@ -0,0 +1,189 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - ["@google-cloud/spanner.BackupStatic", "@google-cloud/spanner/backup.BackupStatic", ""] + - ["@google-cloud/spanner.BackupStatic", "@google-cloud/spanner/backup", "Member[Backup]"] + - ["@google-cloud/spanner.BackupStatic", "@google-cloud/spanner", "Member[Backup]"] + - ["@google-cloud/spanner.BatchTransaction", "@google-cloud/spanner/batch-transaction.BatchTransaction", ""] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.DatabaseStatic", Instance] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.Instance", "Member[database].ReturnValue"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.SessionPool", "Member[database]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.SessionPoolStatic", "Argument[0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.SessionStatic", "Argument[0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.Table", "Member[database]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner.TableStatic", "Argument[0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/database.Database", ""] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/database.DatabaseCallback", "TypeVar[@google-cloud/spanner/common.ResourceCallback.0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/database.RestoreDatabaseCallback", "TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/database.SessionPoolConstructor", "Argument[0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/instance.CreateDatabaseCallback", "TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]"] + - ["@google-cloud/spanner.Database", "@google-cloud/spanner/instance.GetDatabasesCallback", "TypeVar[@google-cloud/spanner/common.RequestCallback.0]"] + - ["@google-cloud/spanner.DatabaseStatic", "@google-cloud/spanner/database.DatabaseStatic", ""] + - ["@google-cloud/spanner.DatabaseStatic", "@google-cloud/spanner/database", "Member[Database]"] + - ["@google-cloud/spanner.DatabaseStatic", "@google-cloud/spanner", "Member[Database]"] + - ["@google-cloud/spanner.GetInstancesCallback", "@google-cloud/spanner.Spanner", "Member[getInstances].Argument[1]"] + - ["@google-cloud/spanner.GetInstancesCallback", "@google-cloud/spanner.Spanner", "Member[getInstances].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner.GetInstancesCallback", "@google-cloud/spanner/build/src.GetInstancesCallback", ""] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner.BackupStatic", "Argument[0]"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner.DatabaseStatic", "Argument[0]"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner.GetInstancesCallback", "TypeVar[@google-cloud/spanner/common.PagedCallback.0]"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner.InstanceStatic", Instance] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner.Spanner", "Member[instance].ReturnValue"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner/instance.CreateInstanceCallback", "TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner/instance.GetInstanceCallback", "TypeVar[@google-cloud/spanner/common.ResourceCallback.0]"] + - ["@google-cloud/spanner.Instance", "@google-cloud/spanner/instance.Instance", ""] + - ["@google-cloud/spanner.InstanceStatic", "@google-cloud/spanner/instance.InstanceStatic", ""] + - ["@google-cloud/spanner.InstanceStatic", "@google-cloud/spanner/instance", "Member[Instance]"] + - ["@google-cloud/spanner.InstanceStatic", "@google-cloud/spanner", "Member[Instance]"] + - ["@google-cloud/spanner.PartitionedDml", "@google-cloud/spanner.PartitionedDmlStatic", Instance] + - ["@google-cloud/spanner.PartitionedDml", "@google-cloud/spanner.Session", "Member[partitionedDml].ReturnValue"] + - ["@google-cloud/spanner.PartitionedDml", "@google-cloud/spanner/transaction.PartitionedDml", ""] + - ["@google-cloud/spanner.PartitionedDmlStatic", "@google-cloud/spanner/transaction.PartitionedDmlStatic", ""] + - ["@google-cloud/spanner.PartitionedDmlStatic", "@google-cloud/spanner/transaction", "Member[PartitionedDml]"] + - ["@google-cloud/spanner.PartitionedDmlStatic", "@google-cloud/spanner", "Member[PartitionedDml]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.Database", "Member[_runPartitionedUpdate].Argument[0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.Database", "Member[makePooledRequest_].WithArity[1].ReturnValue.Awaited"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.Database", "Member[session].ReturnValue"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.SessionPool", "Member[_acquire,_getSession].ReturnValue.Awaited"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.SessionPool", "Member[_borrow,_destroy,_isValidSession,_ping,_prepareTransaction,_release,release].Argument[0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.SessionPool", "Member[_borrowFrom,_borrowNextAvailableSession].ReturnValue"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.SessionPool", "Member[_getIdleSessions].ReturnValue.ArrayElement"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.SessionStatic", Instance] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner.Snapshot", "Member[session]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/batch-transaction.TransactionIdentifier", "Member[session]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/database.BatchCreateSessionsCallback", "TypeVar[@google-cloud/spanner/common.ResourceCallback.0].ArrayElement"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/database.CreateSessionCallback", "TypeVar[@google-cloud/spanner/common.ResourceCallback.0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/database.GetSessionsCallback", "TypeVar[@google-cloud/spanner/common.RequestCallback.0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/database.PoolRequestCallback", "TypeVar[@google-cloud/spanner/common.RequestCallback.0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/session-pool.GetReadSessionCallback", "TypeVar[@google-cloud/spanner/common.NormalCallback.0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/session-pool.GetWriteSessionCallback", "Argument[1]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/session-pool.SessionPoolInterface", "Member[release].Argument[0]"] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/session.Session", ""] + - ["@google-cloud/spanner.Session", "@google-cloud/spanner/transaction-runner.Runner", "Member[session]"] + - ["@google-cloud/spanner.SessionPool", "@google-cloud/spanner.SessionPoolStatic", Instance] + - ["@google-cloud/spanner.SessionPool", "@google-cloud/spanner/instance.CreateDatabaseOptions", "Member[poolCtor]"] + - ["@google-cloud/spanner.SessionPool", "@google-cloud/spanner/session-pool.SessionPool", ""] + - ["@google-cloud/spanner.SessionPoolStatic", "@google-cloud/spanner/session-pool.SessionPoolStatic", ""] + - ["@google-cloud/spanner.SessionPoolStatic", "@google-cloud/spanner/session-pool", "Member[SessionPool]"] + - ["@google-cloud/spanner.SessionPoolStatic", "@google-cloud/spanner", "Member[SessionPool]"] + - ["@google-cloud/spanner.SessionStatic", "@google-cloud/spanner/session.SessionStatic", ""] + - ["@google-cloud/spanner.SessionStatic", "@google-cloud/spanner/session", "Member[Session]"] + - ["@google-cloud/spanner.SessionStatic", "@google-cloud/spanner", "Member[Session]"] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner.Session", "Member[snapshot].ReturnValue"] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner.SnapshotStatic", Instance] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner/batch-transaction.BatchTransaction", ""] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner/database.GetSnapshotCallback", "TypeVar[@google-cloud/spanner/common.NormalCallback.0]"] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner/transaction.Dml", ""] + - ["@google-cloud/spanner.Snapshot", "@google-cloud/spanner/transaction.Snapshot", ""] + - ["@google-cloud/spanner.SnapshotStatic", "@google-cloud/spanner/transaction.SnapshotStatic", ""] + - ["@google-cloud/spanner.SnapshotStatic", "@google-cloud/spanner/transaction", "Member[Snapshot]"] + - ["@google-cloud/spanner.SnapshotStatic", "@google-cloud/spanner", "Member[Snapshot]"] + - ["@google-cloud/spanner.Spanner", "@google-cloud/spanner.InstanceStatic", "Argument[0]"] + - ["@google-cloud/spanner.Spanner", "@google-cloud/spanner.SpannerStatic", Instance] + - ["@google-cloud/spanner.SpannerStatic", "@google-cloud/spanner", "Member[Spanner]"] + - ["@google-cloud/spanner.Table", "@google-cloud/spanner.Database", "Member[table].ReturnValue"] + - ["@google-cloud/spanner.Table", "@google-cloud/spanner.TableStatic", Instance] + - ["@google-cloud/spanner.Table", "@google-cloud/spanner/table.CreateTableCallback", "TypeVar[@google-cloud/spanner/common.LongRunningCallback.0]"] + - ["@google-cloud/spanner.Table", "@google-cloud/spanner/table.Table", ""] + - ["@google-cloud/spanner.TableStatic", "@google-cloud/spanner/table.TableStatic", ""] + - ["@google-cloud/spanner.TableStatic", "@google-cloud/spanner/table", "Member[Table]"] + - ["@google-cloud/spanner.TableStatic", "@google-cloud/spanner", "Member[Table]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner.Session", "Member[transaction].ReturnValue"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner.Session", "Member[txn]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner.TransactionStatic", Instance] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/database.GetTransactionCallback", "TypeVar[@google-cloud/spanner/common.NormalCallback.0]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/session-pool.GetWriteSessionCallback", "Argument[2]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback", "Argument[0]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/transaction-runner.RunTransactionCallback", "TypeVar[@google-cloud/spanner/common.NormalCallback.0]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/transaction-runner.Runner", "Member[getTransaction].ReturnValue.Awaited"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/transaction-runner.Runner", "Member[transaction]"] + - ["@google-cloud/spanner.Transaction", "@google-cloud/spanner/transaction.Transaction", ""] + - ["@google-cloud/spanner.TransactionStatic", "@google-cloud/spanner/transaction.TransactionStatic", ""] + - ["@google-cloud/spanner.TransactionStatic", "@google-cloud/spanner/transaction", "Member[Transaction]"] + - ["@google-cloud/spanner.TransactionStatic", "@google-cloud/spanner", "Member[Transaction]"] + - ["@google-cloud/spanner.v1.SpannerClient", "@google-cloud/spanner.v1.SpannerClientStatic", Instance] + - ["@google-cloud/spanner.v1.SpannerClient", "@google-cloud/spanner/v1/spanner_client.SpannerClient", ""] + - ["@google-cloud/spanner.v1.SpannerClientStatic", "@google-cloud/spanner/v1/spanner_client.SpannerClientStatic", ""] + - ["@google-cloud/spanner.v1.SpannerClientStatic", "@google-cloud/spanner/v1/spanner_client", "Member[SpannerClient]"] + - ["@google-cloud/spanner.v1.SpannerClientStatic", "@google-cloud/spanner", "Member[v1].Member[SpannerClient]"] + - ["@google-cloud/spanner.~SpannerObject", "@google-cloud/spanner.Database", ""] + - ["@google-cloud/spanner.~SpannerObject", "@google-cloud/spanner.Snapshot", ""] + - ["@google-cloud/spanner.~SpannerObject", "@google-cloud/spanner.Transaction", ""] + - ["@google-cloud/spanner.~SpannerObject", "@google-cloud/spanner.v1.SpannerClient", ""] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.BatchTransaction", "Member[createQueryPartitions]"] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.Database", "Member[run,runPartitionedUpdate,runStream]"] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.PartitionedDml", "Member[runUpdate]"] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.Snapshot", "Member[run,runStream]"] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.Transaction", "Member[run,runStream,runUpdate]"] + - ["@google-cloud/spanner.~SqlExecutorDirect", "@google-cloud/spanner.v1.SpannerClient", "Member[executeSql,executeStreamingSql,partitionQuery]"] + - ["@google-cloud/spanner/batch-transaction.BatchTransaction", "@google-cloud/spanner.Database", "Member[batchTransaction].ReturnValue"] + - ["@google-cloud/spanner/batch-transaction.BatchTransaction", "@google-cloud/spanner/batch-transaction.BatchTransactionStatic", Instance] + - ["@google-cloud/spanner/batch-transaction.BatchTransaction", "@google-cloud/spanner/database.CreateBatchTransactionCallback", "TypeVar[@google-cloud/spanner/common.ResourceCallback.0]"] + - ["@google-cloud/spanner/batch-transaction.BatchTransactionStatic", "@google-cloud/spanner/batch-transaction", "Member[BatchTransaction]"] + - ["@google-cloud/spanner/batch-transaction.TransactionIdentifier", "@google-cloud/spanner.Database", "Member[batchTransaction].Argument[0]"] + - ["@google-cloud/spanner/batch-transaction.TransactionIdentifier", "@google-cloud/spanner/batch-transaction.BatchTransaction", "Member[identifier].ReturnValue"] + - ["@google-cloud/spanner/database.BatchCreateSessionsCallback", "@google-cloud/spanner.Database", "Member[batchCreateSessions].Argument[1]"] + - ["@google-cloud/spanner/database.CreateBatchTransactionCallback", "@google-cloud/spanner.Database", "Member[createBatchTransaction].Argument[1]"] + - ["@google-cloud/spanner/database.CreateBatchTransactionCallback", "@google-cloud/spanner.Database", "Member[createBatchTransaction].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/database.CreateSessionCallback", "@google-cloud/spanner.Database", "Member[createSession].Argument[1]"] + - ["@google-cloud/spanner/database.CreateSessionCallback", "@google-cloud/spanner.Database", "Member[createSession].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/database.DatabaseCallback", "@google-cloud/spanner.Database", "Member[get].Argument[1]"] + - ["@google-cloud/spanner/database.DatabaseCallback", "@google-cloud/spanner.Database", "Member[get].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/database.GetSessionsCallback", "@google-cloud/spanner.Database", "Member[getSessions].Argument[1]"] + - ["@google-cloud/spanner/database.GetSessionsCallback", "@google-cloud/spanner.Database", "Member[getSessions].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/database.GetSnapshotCallback", "@google-cloud/spanner.Database", "Member[getSnapshot].Argument[1]"] + - ["@google-cloud/spanner/database.GetSnapshotCallback", "@google-cloud/spanner.Database", "Member[getSnapshot].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/database.GetTransactionCallback", "@google-cloud/spanner.Database", "Member[getTransaction].Argument[0]"] + - ["@google-cloud/spanner/database.PoolRequestCallback", "@google-cloud/spanner.Database", "Member[makePooledRequest_].Argument[1]"] + - ["@google-cloud/spanner/database.RestoreDatabaseCallback", "@google-cloud/spanner.Database", "Member[restore].Argument[1,2]"] + - ["@google-cloud/spanner/database.SessionPoolConstructor", "@google-cloud/spanner.DatabaseStatic", "Argument[2]"] + - ["@google-cloud/spanner/database.SessionPoolConstructor", "@google-cloud/spanner.Instance", "Member[database].Argument[1]"] + - ["@google-cloud/spanner/instance.CreateDatabaseCallback", "@google-cloud/spanner.Instance", "Member[createDatabase].Argument[2]"] + - ["@google-cloud/spanner/instance.CreateDatabaseCallback", "@google-cloud/spanner.Instance", "Member[createDatabase].WithArity[2].Argument[1]"] + - ["@google-cloud/spanner/instance.CreateDatabaseOptions", "@google-cloud/spanner.Instance", "Member[createDatabase].WithArity[1,2,3].Argument[1]"] + - ["@google-cloud/spanner/instance.CreateInstanceCallback", "@google-cloud/spanner.Spanner", "Member[createInstance].Argument[2]"] + - ["@google-cloud/spanner/instance.GetDatabasesCallback", "@google-cloud/spanner.Instance", "Member[getDatabases].Argument[1]"] + - ["@google-cloud/spanner/instance.GetDatabasesCallback", "@google-cloud/spanner.Instance", "Member[getDatabases].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/instance.GetInstanceCallback", "@google-cloud/spanner.Instance", "Member[get].Argument[1]"] + - ["@google-cloud/spanner/instance.GetInstanceCallback", "@google-cloud/spanner.Instance", "Member[get].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/session-pool.GetReadSessionCallback", "@google-cloud/spanner.SessionPool", "Member[getReadSession].Argument[0]"] + - ["@google-cloud/spanner/session-pool.GetReadSessionCallback", "@google-cloud/spanner/session-pool.SessionPoolInterface", "Member[getReadSession].Argument[0]"] + - ["@google-cloud/spanner/session-pool.GetWriteSessionCallback", "@google-cloud/spanner.SessionPool", "Member[getWriteSession].Argument[0]"] + - ["@google-cloud/spanner/session-pool.GetWriteSessionCallback", "@google-cloud/spanner/session-pool.SessionPoolInterface", "Member[getWriteSession].Argument[0]"] + - ["@google-cloud/spanner/session-pool.SessionPoolInterface", "@google-cloud/spanner.Database", "Member[pool_]"] + - ["@google-cloud/spanner/session-pool.SessionPoolInterface", "@google-cloud/spanner.SessionPool", ""] + - ["@google-cloud/spanner/session-pool.SessionPoolInterface", "@google-cloud/spanner/database.SessionPoolConstructor", Instance] + - ["@google-cloud/spanner/table.CreateTableCallback", "@google-cloud/spanner.Database", "Member[createTable].Argument[2]"] + - ["@google-cloud/spanner/table.CreateTableCallback", "@google-cloud/spanner.Database", "Member[createTable].WithArity[2].Argument[1]"] + - ["@google-cloud/spanner/table.CreateTableCallback", "@google-cloud/spanner.Table", "Member[create].Argument[2]"] + - ["@google-cloud/spanner/table.CreateTableCallback", "@google-cloud/spanner.Table", "Member[create].WithArity[2].Argument[1]"] + - ["@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback", "@google-cloud/spanner.Database", "Member[runTransactionAsync].Argument[1]"] + - ["@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback", "@google-cloud/spanner.Database", "Member[runTransactionAsync].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/transaction-runner.AsyncRunTransactionCallback", "@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic", "Argument[2]"] + - ["@google-cloud/spanner/transaction-runner.AsyncTransactionRunner", "@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic", Instance] + - ["@google-cloud/spanner/transaction-runner.AsyncTransactionRunnerStatic", "@google-cloud/spanner/transaction-runner", "Member[AsyncTransactionRunner]"] + - ["@google-cloud/spanner/transaction-runner.RunTransactionCallback", "@google-cloud/spanner.Database", "Member[runTransaction].Argument[1]"] + - ["@google-cloud/spanner/transaction-runner.RunTransactionCallback", "@google-cloud/spanner.Database", "Member[runTransaction].WithArity[1].Argument[0]"] + - ["@google-cloud/spanner/transaction-runner.RunTransactionCallback", "@google-cloud/spanner/transaction-runner.TransactionRunnerStatic", "Argument[2]"] + - ["@google-cloud/spanner/transaction-runner.Runner", "@google-cloud/spanner/transaction-runner.AsyncTransactionRunner", ""] + - ["@google-cloud/spanner/transaction-runner.Runner", "@google-cloud/spanner/transaction-runner.RunnerStatic", Instance] + - ["@google-cloud/spanner/transaction-runner.Runner", "@google-cloud/spanner/transaction-runner.TransactionRunner", ""] + - ["@google-cloud/spanner/transaction-runner.RunnerStatic", "@google-cloud/spanner/transaction-runner", "Member[Runner]"] + - ["@google-cloud/spanner/transaction-runner.TransactionRunner", "@google-cloud/spanner/transaction-runner.TransactionRunnerStatic", Instance] + - ["@google-cloud/spanner/transaction-runner.TransactionRunnerStatic", "@google-cloud/spanner/transaction-runner", "Member[TransactionRunner]"] + - ["@google-cloud/spanner/transaction.Dml", "@google-cloud/spanner.PartitionedDml", ""] + - ["@google-cloud/spanner/transaction.Dml", "@google-cloud/spanner.Transaction", ""] + - ["@google-cloud/spanner/transaction.Dml", "@google-cloud/spanner/transaction.DmlStatic", Instance] + - ["@google-cloud/spanner/transaction.DmlStatic", "@google-cloud/spanner/transaction", "Member[Dml]"] + + - addsTo: + pack: codeql/javascript-all + extensible: typeVariableModel + data: + - ["@google-cloud/spanner/common.LongRunningCallback.0", "Argument[1]"] + - ["@google-cloud/spanner/common.NormalCallback.0", "Argument[1]"] + - ["@google-cloud/spanner/common.PagedCallback.0", "Argument[1].ArrayElement"] + - ["@google-cloud/spanner/common.RequestCallback.0", "TypeVar[@google-cloud/spanner/common.NormalCallback.0,@google-cloud/spanner/common.PagedCallback.0]"] + - ["@google-cloud/spanner/common.ResourceCallback.0", "Argument[1]"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/Model.qll b/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/Model.qll deleted file mode 100644 index 86bc0efd72b..00000000000 --- a/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/Model.qll +++ /dev/null @@ -1,37 +0,0 @@ -/** Generated model file */ - -private import javascript - -private class Types extends ModelInput::TypeModelCsv { - override predicate row(string row) { - row = - [ - "sqlite3.Database;sqlite3.Database;Member[addListener,all,each,exec,get,on,once,prependListener,prependOnceListener,run].ReturnValue", // - "sqlite3.Database;sqlite3.DatabaseStatic;Instance", // - "sqlite3.Database;sqlite3.Statement;Member[finalize].ReturnValue", // - "sqlite3.Database;sqlite3;Member[cached].Member[Database].ReturnValue", // - "sqlite3.DatabaseStatic;sqlite3.sqlite3;Member[Database]", // - "sqlite3.DatabaseStatic;sqlite3;Member[Database]", // - "sqlite3.RunResult;sqlite3.sqlite3;Member[RunResult]", // - "sqlite3.Statement;sqlite3.Database;Member[prepare].ReturnValue", // - "sqlite3.Statement;sqlite3.RunResult;", // - "sqlite3.Statement;sqlite3.Statement;Member[all,bind,each,get,reset,run].ReturnValue", // - "sqlite3.Statement;sqlite3.StatementStatic;Instance", // - "sqlite3.StatementStatic;sqlite3.sqlite3;Member[Statement]", // - "sqlite3.StatementStatic;sqlite3;Member[Statement]", // - "sqlite3.sqlite3;sqlite3.sqlite3;Member[verbose].ReturnValue", // - "sqlite3.sqlite3;sqlite3;Member[verbose].ReturnValue", // - ] - } -} - -private class Summaries extends ModelInput::SummaryModelCsv { - override predicate row(string row) { - row = - [ - "sqlite3.Database;;;Member[addListener,all,each,exec,get,on,once,prependListener,prependOnceListener,run].ReturnValue;type", // - "sqlite3.Statement;;;Member[all,bind,each,get,reset,run].ReturnValue;type", // - "sqlite3.sqlite3;;;Member[verbose].ReturnValue;type", // - ] - } -} diff --git a/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/model.yml b/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/model.yml new file mode 100644 index 00000000000..643ef4efb25 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/sqlite3/model.yml @@ -0,0 +1,28 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [sqlite3.Database, sqlite3.Database, "Member[addListener,all,each,exec,get,on,once,prependListener,prependOnceListener,run].ReturnValue"] + - [sqlite3.Database, sqlite3.DatabaseStatic, Instance] + - [sqlite3.Database, sqlite3.Statement, "Member[finalize].ReturnValue"] + - [sqlite3.Database, sqlite3, "Member[cached].Member[Database].ReturnValue"] + - [sqlite3.DatabaseStatic, sqlite3.sqlite3, "Member[Database]"] + - [sqlite3.DatabaseStatic, sqlite3, "Member[Database]"] + - [sqlite3.RunResult, sqlite3.sqlite3, "Member[RunResult]"] + - [sqlite3.Statement, sqlite3.Database, "Member[prepare].ReturnValue"] + - [sqlite3.Statement, sqlite3.RunResult, ""] + - [sqlite3.Statement, sqlite3.Statement, "Member[all,bind,each,get,reset,run].ReturnValue"] + - [sqlite3.Statement, sqlite3.StatementStatic, Instance] + - [sqlite3.StatementStatic, sqlite3.sqlite3, "Member[Statement]"] + - [sqlite3.StatementStatic, sqlite3, "Member[Statement]"] + - [sqlite3.sqlite3, sqlite3.sqlite3, "Member[verbose].ReturnValue"] + - [sqlite3.sqlite3, sqlite3, "Member[verbose].ReturnValue"] + + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [sqlite3.Database, "", "", "Member[addListener,all,each,exec,get,on,once,prependListener,prependOnceListener,run].ReturnValue", type] + - [sqlite3.Statement, "", "", "Member[all,bind,each,get,reset,run].ReturnValue", type] + - [sqlite3.sqlite3, "", "", "Member[verbose].ReturnValue", type] diff --git a/misc/scripts/check-query-ids.py b/misc/scripts/check-query-ids.py new file mode 100644 index 00000000000..aa06ae3a6a5 --- /dev/null +++ b/misc/scripts/check-query-ids.py @@ -0,0 +1,44 @@ +from pathlib import Path +import re +import sys +from typing import Dict, List, Optional + +ID = re.compile(r" +\* +@id\s*(.*)") + +def get_query_id(query_path: Path) -> Optional[str]: + with open(query_path) as f: + for line in f: + m = ID.match(line) + if m: + return m.group(1) + return None + +def main(): + # Map query IDs to paths of queries with those IDs. We want to check that this is a 1:1 map. + query_ids: Dict[str, List[str]] = {} + + # Just check src folders for now to avoid churn + for query_path in Path().glob("**/src/**/*.ql"): + # Skip compiled query packs + if any(p == ".codeql" for p in query_path.parts): + continue + query_id = get_query_id(query_path) + if query_id is not None: + query_ids.setdefault(query_id, []).append(str(query_path)) + + fail = False + for query_id, query_paths in query_ids.items(): + if len(query_paths) > 1: + fail = True + print(f"Query ID {query_id} is used in multiple queries:") + for query_path in query_paths: + print(f" - {query_path}") + + if fail: + print("FAIL: duplicate query IDs found in src folders. Please assign these queries unique IDs.") + sys.exit(1) + else: + print("PASS: no duplicate query IDs found in src folders.") + +if __name__ == "__main__": + main() diff --git a/misc/scripts/models-as-data/convert_extensions.py b/misc/scripts/models-as-data/convert_extensions.py index 6a05ba62238..51e1e30f389 100644 --- a/misc/scripts/models-as-data/convert_extensions.py +++ b/misc/scripts/models-as-data/convert_extensions.py @@ -74,8 +74,8 @@ class Converter: summaries = self.getAddsTo("ExtractSummaries.ql", helpers.summaryModelPredicate) sources = self.getAddsTo("ExtractSources.ql", helpers.sourceModelPredicate) sinks = self.getAddsTo("ExtractSinks.ql", helpers.sinkModelPredicate) - negativeSummaries = self.getAddsTo("ExtractNegativeSummaries.ql", helpers.negativeSummaryModelPredicate) - return merge(sources, sinks, summaries, negativeSummaries) + neutrals = self.getAddsTo("ExtractNeutrals.ql", helpers.neutralModelPredicate) + return merge(sources, sinks, summaries, neutrals) def save(self, extensions): diff --git a/misc/scripts/models-as-data/generate_flow_model.py b/misc/scripts/models-as-data/generate_flow_model.py index cc99e627383..30f90000d4c 100644 --- a/misc/scripts/models-as-data/generate_flow_model.py +++ b/misc/scripts/models-as-data/generate_flow_model.py @@ -30,7 +30,7 @@ class Generator: self.generateSinks = False self.generateSources = False self.generateSummaries = False - self.generateNegativeSummaries = False + self.generateNeutrals = False self.generateTypeBasedSummaries = False self.dryRun = False self.dirname = "model-generator" @@ -49,7 +49,7 @@ Which models are generated is controlled by the flags: --with-sinks --with-sources --with-summaries - --with-negative-summaries + --with-neutrals --with-typebased-summaries (Experimental) If none of these flags are specified, all models are generated except for the type based models. @@ -102,9 +102,9 @@ Requirements: `codeql` should both appear on your path. sys.argv.remove("--with-summaries") generator.generateSummaries = True - if "--with-negative-summaries" in sys.argv: - sys.argv.remove("--with-negative-summaries") - generator.generateNegativeSummaries = True + if "--with-neutrals" in sys.argv: + sys.argv.remove("--with-neutrals") + generator.generateNeutrals = True if "--with-typebased-summaries" in sys.argv: sys.argv.remove("--with-typebased-summaries") @@ -114,8 +114,8 @@ Requirements: `codeql` should both appear on your path. sys.argv.remove("--dry-run") generator.dryRun = True - if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNegativeSummaries and not generator.generateTypeBasedSummaries: - generator.generateSinks = generator.generateSources = generator.generateSummaries = generator.generateNegativeSummaries = True + if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNeutrals and not generator.generateTypeBasedSummaries: + generator.generateSinks = generator.generateSources = generator.generateSummaries = generator.generateNeutrals = True if len(sys.argv) < 3 or len(sys.argv) > 4: generator.printHelp() @@ -168,21 +168,15 @@ Requirements: `codeql` should both appear on your path. else: sourceAddsTo = "" - if self.generateNegativeSummaries: - negativeSummaryAddsTo = self.getAddsTo("CaptureNegativeSummaryModels.ql", "extNegativeSummaryModel") + if self.generateNeutrals: + neutralAddsTo = self.getAddsTo("CaptureNeutralModels.ql", helpers.neutralModelPredicate) else: - negativeSummaryAddsTo = "" + neutralAddsTo = "" - return f""" -# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. -# Definitions of taint steps in the {self.friendlyname} framework. - + return f"""# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. +# Definitions of models for the {self.friendlyname} framework. extensions: -{sinkAddsTo} -{sourceAddsTo} -{summaryAddsTo} -{negativeSummaryAddsTo} - """ +{sinkAddsTo}{sourceAddsTo}{summaryAddsTo}{neutralAddsTo}""" def makeTypeBasedContent(self): if self.generateTypeBasedSummaries: @@ -190,13 +184,10 @@ extensions: else: typeBasedSummaryAddsTo = "" - return f""" -# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. + return f"""# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. # Definitions of type based summaries in the {self.friendlyname} framework. - extensions: -{typeBasedSummaryAddsTo} - """ +{typeBasedSummaryAddsTo}""" def save(self, content, target): with open(target, "w") as targetYml: diff --git a/misc/scripts/models-as-data/helpers.py b/misc/scripts/models-as-data/helpers.py index 94bf16527de..d26514222ef 100644 --- a/misc/scripts/models-as-data/helpers.py +++ b/misc/scripts/models-as-data/helpers.py @@ -7,7 +7,7 @@ import subprocess summaryModelPredicate = "extSummaryModel" sinkModelPredicate = "extSinkModel" sourceModelPredicate = "extSourceModel" -negativeSummaryModelPredicate = "extNegativeSummaryModel" +neutralModelPredicate = "extNeutralModel" addsToTemplate = """ - addsTo: pack: {0} extensible: {1} diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 237c3c5b0bb..a0403aa4b7e 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -6,4 +6,6 @@ extractor: python library: true upgrades: upgrades dependencies: - codeql/regex: ${workspace} \ No newline at end of file + codeql/regex: ${workspace} +dataExtensions: + - semmle/python/frameworks/**/model.yml diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll index 056ed02a874..c78fe0c857d 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImplSpecific.qll @@ -92,11 +92,11 @@ predicate summaryElement( } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. - * Note. Negative flow summaries has not been implemented for Python. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the neutral model is autogenerated. + * Note. Neutral models have not been implemented for Python. */ -predicate negativeSummaryElement(FlowSummary::SummarizedCallable c, boolean generated) { none() } +predicate neutralElement(FlowSummary::SummarizedCallable c, boolean generated) { none() } /** * Gets the summary component for specification component `c`, if any. diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll index 0e744ba801a..1b7e8cb326a 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll @@ -72,6 +72,7 @@ private module API = Specific::API; private module DataFlow = Specific::DataFlow; private import Specific::AccessPathSyntax +private import ApiGraphModelsExtensions as Extensions /** Module containing hooks for providing input data to be interpreted as a model. */ module ModelInput { @@ -236,6 +237,8 @@ predicate sourceModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sourceModel(type, path, kind) } /** Holds if a sink model exists for the given parameters. */ @@ -246,6 +249,8 @@ private predicate sinkModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sinkModel(type, path, kind) } /** Holds if a summary model `row` exists for the given parameters. */ @@ -258,6 +263,8 @@ private predicate summaryModel(string type, string path, string input, string ou row.splitAt(";", 3) = output and row.splitAt(";", 4) = kind ) + or + Extensions::summaryModel(type, path, input, output, kind) } /** Holds if a type model exists for the given parameters. */ @@ -268,6 +275,8 @@ private predicate typeModel(string type1, string type2, string path) { row.splitAt(";", 1) = type2 and row.splitAt(";", 2) = path ) + or + Extensions::typeModel(type1, type2, path) } /** Holds if a type variable model exists for the given parameters. */ @@ -277,6 +286,8 @@ private predicate typeVariableModel(string name, string path) { row.splitAt(";", 0) = name and row.splitAt(";", 1) = path ) + or + Extensions::typeVariableModel(name, path) } /** diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll new file mode 100644 index 00000000000..11c3bb9657e --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -0,0 +1,36 @@ +/** + * Defines extensible predicates for contributing library models from data extensions. + */ + +/** + * Holds if the value at `(type, path)` should be seen as a flow + * source of the given `kind`. + * + * The kind `remote` represents a general remote flow source. + */ +extensible predicate sourceModel(string type, string path, string kind); + +/** + * Holds if the value at `(type, path)` should be seen as a sink + * of the given `kind`. + */ +extensible predicate sinkModel(string type, string path, string kind); + +/** + * Holds if calls to `(type, path)`, the value referred to by `input` + * can flow to the value referred to by `output`. + * + * `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps, + * respectively. + */ +extensible predicate summaryModel(string type, string path, string input, string output, string kind); + +/** + * Holds if `(type2, path)` should be seen as an instance of `type1`. + */ +extensible predicate typeModel(string type1, string type2, string path); + +/** + * Holds if `path` can be substituted for a token `TypeVar[name]`. + */ +extensible predicate typeVariableModel(string name, string path); diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/model.yml b/python/ql/lib/semmle/python/frameworks/data/internal/model.yml new file mode 100644 index 00000000000..46fdcfe96bf --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/data/internal/model.yml @@ -0,0 +1,26 @@ +extensions: + # Contribute empty data sets to avoid errors about an undefined extensionals + - addsTo: + pack: codeql/python-all + extensible: sourceModel + data: [] + + - addsTo: + pack: codeql/python-all + extensible: sinkModel + data: [] + + - addsTo: + pack: codeql/python-all + extensible: summaryModel + data: [] + + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: [] + + - addsTo: + pack: codeql/python-all + extensible: typeVariableModel + data: [] diff --git a/python/ql/src/experimental/Security/CWE-022bis/TarSlip.qhelp b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp.disabled similarity index 97% rename from python/ql/src/experimental/Security/CWE-022bis/TarSlip.qhelp rename to python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp.disabled index 75ba15abf42..ce3ec17c362 100644 --- a/python/ql/src/experimental/Security/CWE-022bis/TarSlip.qhelp +++ b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp.disabled @@ -1,6 +1,7 @@ + diff --git a/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql index e614c1a3d78..80462fc91c0 100755 --- a/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql +++ b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql @@ -4,7 +4,7 @@ * destination file path is within the destination directory can cause files outside * the destination directory to be overwritten. * @kind path-problem - * @id py/tarslip + * @id py/tarslip-extended * @problem.severity error * @security-severity 7.5 * @precision high diff --git a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql b/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql index 008650c86e7..46382ad296d 100644 --- a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql +++ b/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql @@ -6,7 +6,7 @@ * @problem.severity error * @security-severity 2.9 * @sub-severity high - * @id py/reflective-xss + * @id py/reflective-xss-email * @tags security * external/cwe/cwe-079 * external/cwe/cwe-116 diff --git a/ruby/ql/lib/change-notes/2022-11-30-actionmailbox.md b/ruby/ql/lib/change-notes/2022-11-30-actionmailbox.md new file mode 100644 index 00000000000..81c737c6b57 --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-11-30-actionmailbox.md @@ -0,0 +1,4 @@ +--- + category: minorAnalysis +--- + * Calls to `mail` and `inbound_mail` in `ActionMailbox` controllers are now considered sources of remote input. \ No newline at end of file diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index e608967f591..5f43a70ddfe 100644 --- a/ruby/ql/lib/codeql/ruby/Frameworks.qll +++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll @@ -7,6 +7,7 @@ private import codeql.ruby.frameworks.ActionCable private import codeql.ruby.frameworks.ActionController private import codeql.ruby.frameworks.ActiveJob private import codeql.ruby.frameworks.ActionMailer +private import codeql.ruby.frameworks.ActionMailbox private import codeql.ruby.frameworks.ActiveRecord private import codeql.ruby.frameworks.ActiveResource private import codeql.ruby.frameworks.ActiveStorage diff --git a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll index 5f3e11d2703..e2cff3d4878 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll @@ -4,7 +4,9 @@ import codeql.ruby.AST import codeql.ruby.DataFlow private import internal.FlowSummaryImpl as Impl private import internal.DataFlowDispatch +private import internal.DataFlowImplCommon as DataFlowImplCommon private import internal.DataFlowPrivate +private import internal.FlowSummaryImplSpecific // import all instances below private module Summaries { @@ -127,6 +129,17 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari */ pragma[nomagic] predicate propagatesFlowExt(string input, string output, boolean preservesValue) { none() } + + /** + * Gets the synthesized parameter that results from an input specification + * that starts with `Argument[s]` for this library callable. + */ + DataFlow::ParameterNode getParameter(string s) { + exists(ParameterPosition pos | + DataFlowImplCommon::parameterNode(result, TLibraryCallable(this), pos) and + s = getParameterPositionCsv(pos) + ) + } } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll index 0fde6438872..7e569972bb6 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll @@ -63,11 +63,11 @@ predicate summaryElement( } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. - * Note. Negative flow summaries has not been implemented for ruby. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the neutral model is autogenerated. + * Note. Neutral models have not been implemented for ruby. */ -predicate negativeSummaryElement(FlowSummary::SummarizedCallable c, boolean generated) { none() } +predicate neutralElement(FlowSummary::SummarizedCallable c, boolean generated) { none() } bindingset[arg] private SummaryComponent interpretElementArg(string arg) { @@ -145,19 +145,32 @@ string getComponentSpecificCsv(SummaryComponent sc) { none() } /** Gets the textual representation of a parameter position in the format used for flow summaries. */ string getParameterPositionCsv(ParameterPosition pos) { - pos.isSelf() and result = "self" - or - pos.isBlock() and result = "block" - or exists(int i | pos.isPositional(i) and result = i.toString() ) or + exists(int i | + pos.isPositionalLowerBound(i) and + result = i + ".." + ) + or exists(string name | pos.isKeyword(name) and result = name + ":" ) + or + pos.isSelf() and + result = "self" + or + pos.isBlock() and + result = "block" + or + pos.isAny() and + result = "any" + or + pos.isAnyNamed() and + result = "any-named" } /** Gets the textual representation of an argument position in the format used for flow summaries. */ diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll new file mode 100644 index 00000000000..13607f67926 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll @@ -0,0 +1,54 @@ +/** + * Models the `ActionMailbox` library, which is part of Rails. + * Version: 7.0.4. + */ + +private import codeql.ruby.AST +private import codeql.ruby.Concepts +private import codeql.ruby.DataFlow +private import codeql.ruby.dataflow.RemoteFlowSources + +/** + * Models the `ActionMailbox` library, which is part of Rails. + * Version: 7.0.4. + */ +module ActionMailbox { + private DataFlow::ClassNode controller() { + result = DataFlow::getConstant("ActionMailbox").getConstant("Base").getADescendentModule() + } + + /** + * A call to `mail` on the return value of + * `ActionMailbox::Base#inbound_email`, or a direct call to + * `ActionMailbox::Base#mail`, which is equivalent. The returned object + * contains data from the incoming email. + */ + class Mail extends DataFlow::CallNode { + Mail() { + this = + [ + controller().getAnInstanceSelf().getAMethodCall("inbound_email").getAMethodCall("mail"), + controller().getAnInstanceSelf().getAMethodCall("mail") + ] + } + } + + /** + * A method call on a `Mail::Message` object which may return data from a remote source. + */ + private class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range { + RemoteContent() { + this = + any(Mail m) + .(DataFlow::LocalSourceNode) + .getAMethodCall([ + "body", "to", "from", "raw_source", "subject", "from_address", + "recipients_addresses", "cc_addresses", "bcc_addresses", "in_reply_to", + "references", "reply_to", "raw_envelope", "to_s", "encoded", "header", "bcc", "cc", + "text_part", "html_part" + ]) + } + + override string getSourceType() { result = "ActionMailbox" } + } +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll index 0e744ba801a..1b7e8cb326a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll @@ -72,6 +72,7 @@ private module API = Specific::API; private module DataFlow = Specific::DataFlow; private import Specific::AccessPathSyntax +private import ApiGraphModelsExtensions as Extensions /** Module containing hooks for providing input data to be interpreted as a model. */ module ModelInput { @@ -236,6 +237,8 @@ predicate sourceModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sourceModel(type, path, kind) } /** Holds if a sink model exists for the given parameters. */ @@ -246,6 +249,8 @@ private predicate sinkModel(string type, string path, string kind) { row.splitAt(";", 1) = path and row.splitAt(";", 2) = kind ) + or + Extensions::sinkModel(type, path, kind) } /** Holds if a summary model `row` exists for the given parameters. */ @@ -258,6 +263,8 @@ private predicate summaryModel(string type, string path, string input, string ou row.splitAt(";", 3) = output and row.splitAt(";", 4) = kind ) + or + Extensions::summaryModel(type, path, input, output, kind) } /** Holds if a type model exists for the given parameters. */ @@ -268,6 +275,8 @@ private predicate typeModel(string type1, string type2, string path) { row.splitAt(";", 1) = type2 and row.splitAt(";", 2) = path ) + or + Extensions::typeModel(type1, type2, path) } /** Holds if a type variable model exists for the given parameters. */ @@ -277,6 +286,8 @@ private predicate typeVariableModel(string name, string path) { row.splitAt(";", 0) = name and row.splitAt(";", 1) = path ) + or + Extensions::typeVariableModel(name, path) } /** diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll new file mode 100644 index 00000000000..11c3bb9657e --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -0,0 +1,36 @@ +/** + * Defines extensible predicates for contributing library models from data extensions. + */ + +/** + * Holds if the value at `(type, path)` should be seen as a flow + * source of the given `kind`. + * + * The kind `remote` represents a general remote flow source. + */ +extensible predicate sourceModel(string type, string path, string kind); + +/** + * Holds if the value at `(type, path)` should be seen as a sink + * of the given `kind`. + */ +extensible predicate sinkModel(string type, string path, string kind); + +/** + * Holds if calls to `(type, path)`, the value referred to by `input` + * can flow to the value referred to by `output`. + * + * `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps, + * respectively. + */ +extensible predicate summaryModel(string type, string path, string input, string output, string kind); + +/** + * Holds if `(type2, path)` should be seen as an instance of `type1`. + */ +extensible predicate typeModel(string type1, string type2, string path); + +/** + * Holds if `path` can be substituted for a token `TypeVar[name]`. + */ +extensible predicate typeVariableModel(string name, string path); diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/model.yml b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/model.yml new file mode 100644 index 00000000000..f69da6cc363 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/model.yml @@ -0,0 +1,26 @@ +extensions: + # Contribute empty data sets to avoid errors about an undefined extensionals + - addsTo: + pack: codeql/ruby-all + extensible: sourceModel + data: [] + + - addsTo: + pack: codeql/ruby-all + extensible: sinkModel + data: [] + + - addsTo: + pack: codeql/ruby-all + extensible: summaryModel + data: [] + + - addsTo: + pack: codeql/ruby-all + extensible: typeModel + data: [] + + - addsTo: + pack: codeql/ruby-all + extensible: typeVariableModel + data: [] diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 0b89e5ea156..3c6c6d2d66a 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -8,3 +8,6 @@ library: true dependencies: codeql/ssa: ${workspace} codeql/regex: ${workspace} + codeql/ssa: 0.0.1 +dataExtensions: + - codeql/ruby/frameworks/**/model.yml diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected new file mode 100644 index 00000000000..b7324362d14 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected @@ -0,0 +1,12 @@ +messageInstances +| action_mailbox.rb:3:5:3:8 | call to mail | +| action_mailbox.rb:4:5:4:8 | call to mail | +| action_mailbox.rb:6:5:6:10 | call to mail | +| action_mailbox.rb:10:5:10:8 | call to mail | +| action_mailbox.rb:16:9:16:12 | call to mail | +remoteFlowSources +| action_mailbox.rb:3:5:3:13 | call to body | +| action_mailbox.rb:4:5:4:11 | call to to | +| action_mailbox.rb:6:5:6:13 | call to to | +| action_mailbox.rb:10:5:10:18 | call to text_part | +| action_mailbox.rb:16:9:16:23 | call to raw_source | diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql new file mode 100644 index 00000000000..cd083bf6a06 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql @@ -0,0 +1,7 @@ +private import codeql.ruby.frameworks.ActionMailbox +private import codeql.ruby.DataFlow +private import codeql.ruby.dataflow.RemoteFlowSources + +query predicate messageInstances(ActionMailbox::Mail c) { any() } + +query predicate remoteFlowSources(RemoteFlowSource r) { any() } diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb b/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb new file mode 100644 index 00000000000..04b007c4be7 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb @@ -0,0 +1,24 @@ +class A < ActionMailbox::Base + def process + mail.body + mail.to + m = inbound_email + m.mail.to + end + + def other_method + mail.text_part + end +end + +class B < A + def process + mail.raw_source + end +end + +class C # not a mailbox class + def process + mail.subject + end +end \ No newline at end of file diff --git a/swift/extractor/SwiftExtractor.cpp b/swift/extractor/SwiftExtractor.cpp index c9410d2f1f3..2cee41cb0e3 100644 --- a/swift/extractor/SwiftExtractor.cpp +++ b/swift/extractor/SwiftExtractor.cpp @@ -12,7 +12,7 @@ #include "swift/extractor/translators/SwiftVisitor.h" #include "swift/extractor/TargetTrapFile.h" #include "swift/extractor/SwiftBuiltinSymbols.h" -#include "swift/extractor/infra/Path.h" +#include "swift/extractor/infra/file/Path.h" using namespace codeql; using namespace std::string_literals; @@ -28,27 +28,23 @@ static void ensureDirectory(const char* label, const fs::path& dir) { } static void archiveFile(const SwiftExtractorConfiguration& config, swift::SourceFile& file) { - ensureDirectory("TRAP", config.trapDir); - ensureDirectory("source archive", config.sourceArchiveDir); + auto source = codeql::resolvePath(file.getFilename()); + auto destination = config.sourceArchiveDir / source.relative_path(); - fs::path srcFilePath = codeql::getCodeQLPath(file.getFilename()); - auto dstFilePath = config.sourceArchiveDir; - dstFilePath += srcFilePath; - - ensureDirectory("source archive destination", dstFilePath.parent_path()); + ensureDirectory("source archive destination", destination.parent_path()); std::error_code ec; - fs::copy(srcFilePath, dstFilePath, fs::copy_options::overwrite_existing, ec); + fs::copy(source, destination, fs::copy_options::overwrite_existing, ec); if (ec) { - std::cerr << "Cannot archive source file " << srcFilePath << " -> " << dstFilePath << ": " + std::cerr << "Cannot archive source file " << source << " -> " << destination << ": " << ec.message() << "\n"; } } static fs::path getFilename(swift::ModuleDecl& module, swift::SourceFile* primaryFile) { if (primaryFile) { - return primaryFile->getFilename().str(); + return resolvePath(primaryFile->getFilename()); } // PCM clang module if (module.isNonSwiftModule()) { @@ -57,7 +53,7 @@ static fs::path getFilename(swift::ModuleDecl& module, swift::SourceFile* primar // Moreover, pcm files may come from caches located in different directories, but are // unambiguously identified by the base file name, so we can discard the absolute directory fs::path filename = "/pcms"; - filename /= getCodeQLPath(module.getModuleFilename()).filename(); + filename /= fs::path{std::string_view{module.getModuleFilename()}}.filename(); filename += "-"; filename += module.getName().str(); return filename; @@ -66,13 +62,13 @@ static fs::path getFilename(swift::ModuleDecl& module, swift::SourceFile* primar // The Builtin module has an empty filename, let's fix that return "/__Builtin__"; } - auto filename = getCodeQLPath(module.getModuleFilename()); + std::string_view filename = module.getModuleFilename(); // there is a special case of a module without an actual filename reporting ``: in this // case we want to avoid the `<>` characters, in case a dirty DB is imported on Windows if (filename == "") { return "/__imports__"; } - return filename; + return resolvePath(filename); } /* The builtin module is special, as it does not publish any top-level declaration diff --git a/swift/extractor/infra/Path.h b/swift/extractor/infra/Path.h deleted file mode 100644 index 09ab7ed1773..00000000000 --- a/swift/extractor/infra/Path.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -namespace codeql { -std::filesystem::path getCodeQLPath(std::string_view path); -} diff --git a/swift/extractor/infra/SwiftLocationExtractor.cpp b/swift/extractor/infra/SwiftLocationExtractor.cpp index a003519f4ce..7c98294804a 100644 --- a/swift/extractor/infra/SwiftLocationExtractor.cpp +++ b/swift/extractor/infra/SwiftLocationExtractor.cpp @@ -5,7 +5,7 @@ #include "swift/extractor/trap/generated/TrapEntries.h" #include "swift/extractor/trap/generated/TrapClasses.h" #include "swift/extractor/infra/SwiftLocationExtractor.h" -#include "swift/extractor/infra/Path.h" +#include "swift/extractor/infra/file/Path.h" using namespace codeql; @@ -17,7 +17,7 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa // invalid locations seem to come from entities synthesized by the compiler return; } - auto file = getCodeQLPath(sourceManager.getDisplayNameForLoc(start)); + auto file = resolvePath(sourceManager.getDisplayNameForLoc(start)); DbLocation entry{{}}; entry.file = fetchFileLabel(file); std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start); @@ -30,7 +30,7 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa } void SwiftLocationExtractor::emitFile(llvm::StringRef path) { - fetchFileLabel(getCodeQLPath(path)); + fetchFileLabel(resolvePath(path)); } TrapLabel SwiftLocationExtractor::fetchFileLabel(const std::filesystem::path& file) { diff --git a/swift/extractor/infra/Path.cpp b/swift/extractor/infra/file/Path.cpp similarity index 87% rename from swift/extractor/infra/Path.cpp rename to swift/extractor/infra/file/Path.cpp index 37b4d13fd0c..f114bfdd41b 100644 --- a/swift/extractor/infra/Path.cpp +++ b/swift/extractor/infra/file/Path.cpp @@ -1,4 +1,4 @@ -#include "swift/extractor/infra/Path.h" +#include "swift/extractor/infra/file/Path.h" #include #include @@ -16,7 +16,7 @@ static bool shouldCanonicalize() { return true; } -std::filesystem::path getCodeQLPath(std::string_view path) { +std::filesystem::path resolvePath(std::string_view path) { std::error_code ec; std::filesystem::path ret = {}; static const auto canonicalize = shouldCanonicalize(); @@ -28,7 +28,7 @@ std::filesystem::path getCodeQLPath(std::string_view path) { if (ec) { std::cerr << "Cannot get " << (canonicalize ? "canonical" : "absolute") << " path: " << std::quoted(path) << ": " << ec.message() << "\n"; - return {}; + return path; } return ret; } diff --git a/swift/extractor/infra/file/Path.h b/swift/extractor/infra/file/Path.h new file mode 100644 index 00000000000..c1a31786454 --- /dev/null +++ b/swift/extractor/infra/file/Path.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace codeql { +std::filesystem::path resolvePath(std::string_view path); +} diff --git a/swift/integration-tests/posix-only/frontend-invocations/Files.expected b/swift/integration-tests/posix-only/frontend-invocations/Files.expected index f13e45d89a5..3bc0826c1f2 100644 --- a/swift/integration-tests/posix-only/frontend-invocations/Files.expected +++ b/swift/integration-tests/posix-only/frontend-invocations/Files.expected @@ -5,4 +5,5 @@ | E.swift:0:0:0:0 | E.swift | | F1.swift:0:0:0:0 | F1.swift | | F2.swift:0:0:0:0 | F2.swift | +| G.swift:0:0:0:0 | G.swift | | file://:0:0:0:0 | | diff --git a/swift/integration-tests/posix-only/frontend-invocations/G.swift b/swift/integration-tests/posix-only/frontend-invocations/G.swift new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/integration-tests/posix-only/frontend-invocations/build.sh b/swift/integration-tests/posix-only/frontend-invocations/build.sh index 03f1148ca05..31cf6e39969 100755 --- a/swift/integration-tests/posix-only/frontend-invocations/build.sh +++ b/swift/integration-tests/posix-only/frontend-invocations/build.sh @@ -16,3 +16,4 @@ $FRONTEND -frontend -c -primary-file E.swift Esup.swift -o E.o $SDK $FRONTEND -frontend -emit-module -primary-file F1.swift F2.swift -module-name F -o F1.swiftmodule $SDK $FRONTEND -frontend -emit-module F1.swift -primary-file F2.swift -module-name F -o F2.swiftmodule $SDK $FRONTEND -merge-modules F1.swiftmodule F2.swiftmodule -o F.swiftmodule $SDK +( cd dir; $FRONTEND -frontend -c ../G.swift $SDK ) diff --git a/swift/integration-tests/posix-only/frontend-invocations/dir/.empty b/swift/integration-tests/posix-only/frontend-invocations/dir/.empty new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index dd0b172a91d..c87d2973783 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -82,7 +82,7 @@ private module Frameworks { private import codeql.swift.frameworks.StandardLibrary.Data private import codeql.swift.frameworks.StandardLibrary.FilePath private import codeql.swift.frameworks.StandardLibrary.InputStream - private import codeql.swift.frameworks.StandardLibrary.NSData + private import codeql.swift.frameworks.StandardLibrary.NsData private import codeql.swift.frameworks.StandardLibrary.NsUrl private import codeql.swift.frameworks.StandardLibrary.String private import codeql.swift.frameworks.StandardLibrary.Url diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll index 6d61d1b4799..61c541d8882 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll @@ -246,14 +246,14 @@ module Public { predicate isAutoGenerated() { none() } } - /** A callable with a flow summary stating there is no flow via the callable. */ - class NegativeSummarizedCallable extends SummarizedCallableBase { - NegativeSummarizedCallable() { negativeSummaryElement(this, _) } + /** A callable where there is no flow via the callable. */ + class NeutralCallable extends SummarizedCallableBase { + NeutralCallable() { neutralElement(this, _) } /** - * Holds if the negative summary is auto generated. + * Holds if the neutral is auto generated. */ - predicate isAutoGenerated() { negativeSummaryElement(this, true) } + predicate isAutoGenerated() { neutralElement(this, true) } } } @@ -1161,9 +1161,9 @@ module Private { string toString() { result = super.toString() } } - /** A flow summary to include in the `negativeSummary/1` query predicate. */ - abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable { - /** Gets the string representation of this callable used by `summary/1`. */ + /** A model to include in the `neutral/1` query predicate. */ + abstract class RelevantNeutralCallable instanceof NeutralCallable { + /** Gets the string representation of this callable used by `neutral/1`. */ abstract string getCallableCsv(); string toString() { result = super.toString() } @@ -1180,13 +1180,13 @@ module Private { if c.isAutoGenerated() then result = "generated" else result = "manual" } - private string renderProvenanceNegative(NegativeSummarizedCallable c) { + private string renderProvenanceNeutral(NeutralCallable c) { if c.isAutoGenerated() then result = "generated" else result = "manual" } /** * A query predicate for outputting flow summaries in semi-colon separated format in QL tests. - * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"", + * The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance", * ext is hardcoded to empty. */ query predicate summary(string csv) { @@ -1205,14 +1205,14 @@ module Private { } /** - * Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes. + * Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes. * The syntax is: "namespace;type;name;signature;provenance"", */ - query predicate negativeSummary(string csv) { - exists(RelevantNegativeSummarizedCallable c | + query predicate neutral(string csv) { + exists(RelevantNeutralCallable c | csv = c.getCallableCsv() // Callable information - + renderProvenanceNegative(c) // provenance + + renderProvenanceNeutral(c) // provenance ) } } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll index b49405c5a4d..cdaded55342 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll @@ -71,11 +71,11 @@ predicate summaryElement( } /** - * Holds if a negative flow summary exists for `c`, which means that there is no - * flow through `c`. The flag `generated` states whether the summary is autogenerated. - * Note. Negative flow summaries has not been implemented for swift. + * Holds if a neutral model exists for `c`, which means that there is no + * flow through `c`. The flag `generated` states whether the neutral model is autogenerated. + * Note. Neutral models have not been implemented for swift. */ -predicate negativeSummaryElement(AbstractFunctionDecl c, boolean generated) { none() } +predicate neutralElement(AbstractFunctionDecl c, boolean generated) { none() } /** * Holds if an external source specification exists for `e` with output specification diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/NSData.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/NsData.qll similarity index 100% rename from swift/ql/lib/codeql/swift/frameworks/StandardLibrary/NSData.qll rename to swift/ql/lib/codeql/swift/frameworks/StandardLibrary/NsData.qll diff --git a/swift/ql/src/queries/Summary/SummaryStats.ql b/swift/ql/src/queries/Summary/SummaryStats.ql index 0408bead921..d8a5d6d7f6d 100644 --- a/swift/ql/src/queries/Summary/SummaryStats.ql +++ b/swift/ql/src/queries/Summary/SummaryStats.ql @@ -9,19 +9,42 @@ import swift import codeql.swift.dataflow.FlowSources import codeql.swift.security.SensitiveExprs +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.TaintTracking -predicate statistic(string what, int value) { - what = "Files" and value = count(File f) - or - what = "Expressions" and value = count(Expr e | not e.getFile() instanceof UnknownFile) - or - what = "Local flow sources" and value = count(LocalFlowSource s) - or - what = "Remote flow sources" and value = count(RemoteFlowSource s) - or - what = "Sensitive expressions" and value = count(SensitiveExpr e) +/** + * A taint configuration for tainted data reaching any node. + */ +class TaintReachConfig extends TaintTracking::Configuration { + TaintReachConfig() { this = "TaintReachConfig" } + + override predicate isSource(DataFlow::Node node) { node instanceof FlowSource } + + override predicate isSink(DataFlow::Node node) { any() } } -from string what, int value +float taintReach() { + exists(TaintReachConfig config, int tainted, int total | + tainted = count(DataFlow::Node n | config.hasFlowTo(n)) and + total = count(DataFlow::Node n) and + result = (tainted * 1000000.0) / total + ) +} + +predicate statistic(string what, string value) { + what = "Files" and value = count(File f).toString() + or + what = "Expressions" and value = count(Expr e | not e.getFile() instanceof UnknownFile).toString() + or + what = "Local flow sources" and value = count(LocalFlowSource s).toString() + or + what = "Remote flow sources" and value = count(RemoteFlowSource s).toString() + or + what = "Sensitive expressions" and value = count(SensitiveExpr e).toString() + or + what = "Taint reach (per million nodes)" and value = taintReach().toString() +} + +from string what, string value where statistic(what, value) select what, value diff --git a/swift/ql/test/library-tests/ast/PrintAst.expected b/swift/ql/test/library-tests/ast/PrintAst.expected index 2ec81962d30..570065b9db1 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.expected +++ b/swift/ql/test/library-tests/ast/PrintAst.expected @@ -1,9 +1,3 @@ -#-----| [ModuleDecl] __ObjC -#-----| [ModuleDecl] cfg -#-----| [ModuleDecl] declarations -#-----| [ModuleDecl] expressions -#-----| [ModuleDecl] patterns -#-----| [ModuleDecl] statements cfg.swift: # 1| [TopLevelCodeDecl] { ... } # 1| getBody(): [BraceStmt] { ... } diff --git a/swift/ql/test/library-tests/ast/PrintAst.ql b/swift/ql/test/library-tests/ast/PrintAst.ql index 245e9ebdb12..05b5fec5a17 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.ql +++ b/swift/ql/test/library-tests/ast/PrintAst.ql @@ -10,5 +10,7 @@ import TestUtils * The hook to customize the entities printed by this query. */ class PrintAstConfigurationOverride extends PrintAstConfiguration { - override predicate shouldPrint(Locatable e) { super.shouldPrint(e) and toBeTested(e) } + override predicate shouldPrint(Locatable e) { + super.shouldPrint(e) and toBeTested(e) and not e instanceof ModuleDecl + } }