From eac5aa26eef6eaec8f706245ce08607430922153 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Wed, 23 Nov 2022 12:57:06 +1300 Subject: [PATCH 001/136] Ruby: Model remote input for ActionMailbox --- ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 + .../codeql/ruby/frameworks/ActionMailbox.qll | 66 +++++++++++++++++++ .../action_mailbox/ActionMailbox.expected | 13 ++++ .../action_mailbox/ActionMailbox.ql | 8 +++ .../action_mailbox/action_mailbox.rb | 22 +++++++ 5 files changed, 110 insertions(+) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index 9896cf23c39..bfd0eabc907 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/frameworks/ActionMailbox.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll new file mode 100644 index 00000000000..2a01651170a --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll @@ -0,0 +1,66 @@ +/** + * 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 method in a mailbox which receives incoming mail. + */ + class Process extends DataFlow::MethodNode { + Process() { this = controller().getAnInstanceMethod() and this.getMethodName() = "process" } + } + + /** + * A call to `ActionMailbox::Base#mail`, which is equivalent to calling `inbound_mail.mail`. + * The returned object contains data from the incoming mail. + */ + class MailCall extends DataFlow::CallNode, Mail::Message::Range { + MailCall() { this = controller().getAnInstanceSelf().getAMethodCall("mail") } + } + + /** + * Models classes from the `mail` library. + * Version: 2.7.1. + */ + module Mail { + /** + * An instance of `Mail::Message`. + */ + class Message extends DataFlow::Node instanceof Message::Range { } + + module Message { + abstract class Range extends DataFlow::Node { } + } + + /** + * A method call on a `Mail::Message` object which may return data from a remote source. + */ + class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range { + RemoteContent() { + this.getReceiver() instanceof Message and + this.getMethodName() = + [ + "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/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..c6705e068e9 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected @@ -0,0 +1,13 @@ +processMethods +| action_mailbox.rb:2:3:5:5 | process | +| action_mailbox.rb:13:5:15:7 | process | +messageInstances +| action_mailbox.rb:3:5:3:8 | call to mail | +| action_mailbox.rb:4:5:4:8 | call to mail | +| action_mailbox.rb:8:5:8:8 | call to mail | +| action_mailbox.rb:14:9:14:12 | call to mail | +remoteContent +| action_mailbox.rb:3:5:3:13 | call to body | +| action_mailbox.rb:4:5:4:11 | call to to | +| action_mailbox.rb:8:5:8:18 | call to text_part | +| action_mailbox.rb:14:9:14: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..2477678b78f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql @@ -0,0 +1,8 @@ +private import codeql.ruby.frameworks.ActionMailbox +private import codeql.ruby.DataFlow + +query predicate processMethods(ActionMailbox::Process p) { any() } + +query predicate messageInstances(ActionMailbox::Mail::Message c) { any() } + +query predicate remoteContent(ActionMailbox::Mail::RemoteContent 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..d9371e89973 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb @@ -0,0 +1,22 @@ +class A < ActionMailbox::Base + def process + mail.body + 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 From 71f2d8f6d81cf386d196abe16e8bf6513af7221c Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Fri, 25 Nov 2022 17:15:50 +1300 Subject: [PATCH 002/136] Ruby: Model ActionMailbox#inbound_mail --- .../lib/codeql/ruby/frameworks/ActionMailbox.qll | 14 +++++++++++--- .../action_mailbox/ActionMailbox.expected | 14 ++++++++------ .../frameworks/action_mailbox/action_mailbox.rb | 2 ++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll index 2a01651170a..8fb0def0a33 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll @@ -25,11 +25,19 @@ module ActionMailbox { } /** - * A call to `ActionMailbox::Base#mail`, which is equivalent to calling `inbound_mail.mail`. - * The returned object contains data from the incoming mail. + * 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 MailCall extends DataFlow::CallNode, Mail::Message::Range { - MailCall() { this = controller().getAnInstanceSelf().getAMethodCall("mail") } + MailCall() { + this = + [ + controller().getAnInstanceSelf().getAMethodCall("inbound_email").getAMethodCall("mail"), + controller().getAnInstanceSelf().getAMethodCall("mail") + ] + } } /** diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected index c6705e068e9..6cce834e488 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected @@ -1,13 +1,15 @@ processMethods -| action_mailbox.rb:2:3:5:5 | process | -| action_mailbox.rb:13:5:15:7 | process | +| action_mailbox.rb:2:3:7:5 | process | +| action_mailbox.rb:15:5:17:7 | process | messageInstances | action_mailbox.rb:3:5:3:8 | call to mail | | action_mailbox.rb:4:5:4:8 | call to mail | -| action_mailbox.rb:8:5:8:8 | call to mail | -| action_mailbox.rb:14:9:14:12 | 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 | remoteContent | action_mailbox.rb:3:5:3:13 | call to body | | action_mailbox.rb:4:5:4:11 | call to to | -| action_mailbox.rb:8:5:8:18 | call to text_part | -| action_mailbox.rb:14:9:14:23 | call to raw_source | +| 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/action_mailbox.rb b/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb index d9371e89973..04b007c4be7 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/action_mailbox.rb @@ -2,6 +2,8 @@ class A < ActionMailbox::Base def process mail.body mail.to + m = inbound_email + m.mail.to end def other_method From b66ea6ed7218fc97a8f43865acf092beb29e9976 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Fri, 25 Nov 2022 17:21:51 +1300 Subject: [PATCH 003/136] Ruby: Simplify ActionMailbox modeling --- .../codeql/ruby/frameworks/ActionMailbox.qll | 43 +++++++------------ .../action_mailbox/ActionMailbox.expected | 2 +- .../action_mailbox/ActionMailbox.ql | 5 ++- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll index 8fb0def0a33..5416fca62a4 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll @@ -30,8 +30,8 @@ module ActionMailbox { * `ActionMailbox::Base#mail`, which is equivalent. The returned object * contains data from the incoming email. */ - class MailCall extends DataFlow::CallNode, Mail::Message::Range { - MailCall() { + class Mail extends DataFlow::CallNode { + Mail() { this = [ controller().getAnInstanceSelf().getAMethodCall("inbound_email").getAMethodCall("mail"), @@ -41,34 +41,21 @@ module ActionMailbox { } /** - * Models classes from the `mail` library. - * Version: 2.7.1. + * A method call on a `Mail::Message` object which may return data from a remote source. */ - module Mail { - /** - * An instance of `Mail::Message`. - */ - class Message extends DataFlow::Node instanceof Message::Range { } - - module Message { - abstract class Range extends DataFlow::Node { } + 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" + ]) } - /** - * A method call on a `Mail::Message` object which may return data from a remote source. - */ - class RemoteContent extends DataFlow::CallNode, RemoteFlowSource::Range { - RemoteContent() { - this.getReceiver() instanceof Message and - this.getMethodName() = - [ - "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" } - } + override string getSourceType() { result = "ActionMailbox" } } } diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected index 6cce834e488..f0325269fb0 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected @@ -7,7 +7,7 @@ messageInstances | 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 | -remoteContent +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 | diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql index 2477678b78f..e0a529dc6c6 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql @@ -1,8 +1,9 @@ private import codeql.ruby.frameworks.ActionMailbox private import codeql.ruby.DataFlow +private import codeql.ruby.dataflow.RemoteFlowSources query predicate processMethods(ActionMailbox::Process p) { any() } -query predicate messageInstances(ActionMailbox::Mail::Message c) { any() } +query predicate messageInstances(ActionMailbox::Mail c) { any() } -query predicate remoteContent(ActionMailbox::Mail::RemoteContent r) { any() } +query predicate remoteFlowSources(RemoteFlowSource r) { any() } From aed4325ee3a2e408c340e6fa71674ac5b81b7ec8 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Wed, 30 Nov 2022 11:50:35 +1300 Subject: [PATCH 004/136] Ruby: Remove unused class --- ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll | 7 ------- .../frameworks/action_mailbox/ActionMailbox.expected | 3 --- .../frameworks/action_mailbox/ActionMailbox.ql | 2 -- 3 files changed, 12 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll index 5416fca62a4..13607f67926 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailbox.qll @@ -17,13 +17,6 @@ module ActionMailbox { result = DataFlow::getConstant("ActionMailbox").getConstant("Base").getADescendentModule() } - /** - * A method in a mailbox which receives incoming mail. - */ - class Process extends DataFlow::MethodNode { - Process() { this = controller().getAnInstanceMethod() and this.getMethodName() = "process" } - } - /** * A call to `mail` on the return value of * `ActionMailbox::Base#inbound_email`, or a direct call to diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected index f0325269fb0..b7324362d14 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.expected @@ -1,6 +1,3 @@ -processMethods -| action_mailbox.rb:2:3:7:5 | process | -| action_mailbox.rb:15:5:17:7 | process | messageInstances | action_mailbox.rb:3:5:3:8 | call to mail | | action_mailbox.rb:4:5:4:8 | call to mail | diff --git a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql index e0a529dc6c6..cd083bf6a06 100644 --- a/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql +++ b/ruby/ql/test/library-tests/frameworks/action_mailbox/ActionMailbox.ql @@ -2,8 +2,6 @@ private import codeql.ruby.frameworks.ActionMailbox private import codeql.ruby.DataFlow private import codeql.ruby.dataflow.RemoteFlowSources -query predicate processMethods(ActionMailbox::Process p) { any() } - query predicate messageInstances(ActionMailbox::Mail c) { any() } query predicate remoteFlowSources(RemoteFlowSource r) { any() } From e3def7c22f504282ab0fc0ff0b72eb48903687f9 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Wed, 30 Nov 2022 11:50:47 +1300 Subject: [PATCH 005/136] Ruby: Add change note --- ruby/ql/lib/change-notes/2022-11-30-actionmailbox.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2022-11-30-actionmailbox.md 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 From 9c27cc0abe5bcc734268ef0a230275c96e845264 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 5 Dec 2022 18:44:16 +0000 Subject: [PATCH 006/136] Add a script to check for duplicate query IDs --- misc/scripts/check-query-ids.py | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 misc/scripts/check-query-ids.py 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() From 6484935d257ce4f34eadd3c00b3da7913fd28bc8 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 5 Dec 2022 18:46:53 +0000 Subject: [PATCH 007/136] Add CI job for check query IDs script --- .github/workflows/check-query-ids.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/check-query-ids.yml 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 From 5b040a9476b8d45dcb7b2111274cdeb01d252f7e Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 5 Dec 2022 18:55:25 +0000 Subject: [PATCH 008/136] Python: Fix duplicate query IDs --- .../Security/CWE-022bis/{TarSlip.qhelp => TarSlipImprov.qhelp} | 0 python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql | 2 +- python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename python/ql/src/experimental/Security/CWE-022bis/{TarSlip.qhelp => TarSlipImprov.qhelp} (100%) diff --git a/python/ql/src/experimental/Security/CWE-022bis/TarSlip.qhelp b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp similarity index 100% rename from python/ql/src/experimental/Security/CWE-022bis/TarSlip.qhelp rename to python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp 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 From 2627632a419cee1f28f5e4fdf7d41e3b6e7e1dc7 Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Mon, 5 Dec 2022 18:56:32 +0000 Subject: [PATCH 009/136] Java: Fix duplicate IDs --- config/identical-files.json | 4 ++ .../CWE-400/LocalThreadResourceAbuse.qhelp | 48 +++++++++++++++++++ .../CWE/CWE-400/LocalThreadResourceAbuse.ql | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp diff --git a/config/identical-files.json b/config/identical-files.json index 0a5d037e226..06bbf55a341 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -580,5 +580,9 @@ "IncompleteMultiCharacterSanitization JS/Ruby": [ "javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll", "ruby/ql/lib/codeql/ruby/security/IncompleteMultiCharacterSanitizationQuery.qll" + ], + "ThreadResourceAbuse help": [ + "java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp", + "java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp" ] } 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 From d2140eb4b10ce8272a6c6397c6660493301a37b1 Mon Sep 17 00:00:00 2001 From: retanoj Date: Tue, 6 Dec 2022 17:07:49 +0800 Subject: [PATCH 010/136] MyBatisAnnotationSqlInjection no @Param case --- .../Security/CWE/CWE-089/MyBatisCommonLib.qll | 16 ++++++++++++++++ .../CWE-089/src/main/MybatisSqlInjection.java | 10 ++++++++++ .../src/main/MybatisSqlInjectionService.java | 8 ++++++++ .../CWE-089/src/main/SqlInjectionMapper.java | 5 +++++ 4 files changed, 39 insertions(+) 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..747bb278109 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -185,5 +185,21 @@ predicate isMybatisXmlOrAnnotationSqlInjection( unsafeExpression.matches("${%}") and ma.getAnArgument() = node.asExpr() ) + or + // Some of method parameters are not annotated with `@Param`, which named in the SQL statement as their name. + // Improper use of these parameters has a SQL injection vulnerability. + // e.g. + // + // ```java + // @Select(select id,name from test where id = #{id} or name = '${name}') + // Test test(Integer id, String name); + // ``` + exists(Parameter param, int idx | + param = ma.getMethod().getParameter(idx) + | + not param.getAnAnnotation().getType() instanceof TypeParam and + unsafeExpression.matches("${" + param.getName() + "}") and + ma.getArgument(idx) = node.asExpr() + ) ) } 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..2e86fa9645f 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 bad10(@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..b48a8dc686d 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 bad9(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..03aa0ee9a50 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); } From fb8559f03a0d4f94b8c8b738c90104a96e47a523 Mon Sep 17 00:00:00 2001 From: retanoj Date: Tue, 6 Dec 2022 18:03:00 +0800 Subject: [PATCH 011/136] tiny fix function name --- .../security/CWE-089/src/main/MybatisSqlInjection.java | 2 +- .../security/CWE-089/src/main/MybatisSqlInjectionService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 2e86fa9645f..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 @@ -106,7 +106,7 @@ public class MybatisSqlInjection { } @GetMapping(value = "good4") - public void bad10(@RequestParam Integer id, @RequestParam String name) { + 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 b48a8dc686d..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,7 +51,7 @@ public class MybatisSqlInjectionService { sqlInjectionMapper.bad9(hashMap); } - public void bad9(Integer id, String name) { + public void bad10(Integer id, String name) { sqlInjectionMapper.bad10(id, name); } From de652e1e27ded3498c0909f8a35b89ab4745fb7d Mon Sep 17 00:00:00 2001 From: retanoj Date: Tue, 6 Dec 2022 18:09:48 +0800 Subject: [PATCH 012/136] expected --- .../MyBatisAnnotationSqlInjection.expected | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) 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..52ec40f1b92 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:70 | Select | this SQL operation | From 2bbd37f9aba3a2756fdca9966a12a0d80e4a3aa9 Mon Sep 17 00:00:00 2001 From: retanoj Date: Tue, 6 Dec 2022 19:27:29 +0800 Subject: [PATCH 013/136] change code snippet to `or` condition --- .../Security/CWE/CWE-089/MyBatisCommonLib.qll | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) 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 747bb278109..27b48fd723a 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -140,6 +140,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 @@ -152,6 +153,8 @@ predicate isMybatisXmlOrAnnotationSqlInjection( unsafeExpression.matches("${param" + (i + 1) + "%}") or unsafeExpression.matches("${arg" + i + "%}") + or + unsafeExpression.matches("${" + ma.getMethod().getParameter(i).getName() + "}") ) and ma.getArgument(i) = node.asExpr() ) @@ -185,21 +188,5 @@ predicate isMybatisXmlOrAnnotationSqlInjection( unsafeExpression.matches("${%}") and ma.getAnArgument() = node.asExpr() ) - or - // Some of method parameters are not annotated with `@Param`, which named in the SQL statement as their name. - // Improper use of these parameters has a SQL injection vulnerability. - // e.g. - // - // ```java - // @Select(select id,name from test where id = #{id} or name = '${name}') - // Test test(Integer id, String name); - // ``` - exists(Parameter param, int idx | - param = ma.getMethod().getParameter(idx) - | - not param.getAnAnnotation().getType() instanceof TypeParam and - unsafeExpression.matches("${" + param.getName() + "}") and - ma.getArgument(idx) = node.asExpr() - ) ) } From b0c86d8e51fab15c32a53f98bcb4a467c8740583 Mon Sep 17 00:00:00 2001 From: retanoj Date: Tue, 6 Dec 2022 21:50:09 +0800 Subject: [PATCH 014/136] change string match to regex match --- .../src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 27b48fd723a..b91702cd30e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -154,7 +154,7 @@ predicate isMybatisXmlOrAnnotationSqlInjection( or unsafeExpression.matches("${arg" + i + "%}") or - unsafeExpression.matches("${" + ma.getMethod().getParameter(i).getName() + "}") + unsafeExpression.regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\s*(,.*?)?\\s*\\}") ) and ma.getArgument(i) = node.asExpr() ) From 8ee418405b2aa5c0961e6e854e743cb19a20a2c2 Mon Sep 17 00:00:00 2001 From: retanoj Date: Wed, 7 Dec 2022 10:06:39 +0800 Subject: [PATCH 015/136] consider blankspace / comma /dot field --- .../Security/CWE/CWE-089/MyBatisCommonLib.qll | 19 +++++++++++-------- .../MyBatisAnnotationSqlInjection.expected | 2 +- .../CWE-089/src/main/SqlInjectionMapper.java | 2 +- .../CWE-089/src/main/SqlInjectionMapper.xml | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) 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 b91702cd30e..93831fcdd24 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,14 @@ 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() = @@ -150,11 +153,11 @@ 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() + "\\s*(,.*?)?\\s*\\}") + unsafeExpression.regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*?\\}") ) and ma.getArgument(i) = node.asExpr() ) @@ -169,7 +172,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/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 52ec40f1b92..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 @@ -42,4 +42,4 @@ nodes 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:70 | 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/SqlInjectionMapper.java b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/SqlInjectionMapper.java index 03aa0ee9a50..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,7 +33,7 @@ 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}'"}) + @Select({"select * from test where id = #{id} and name = '${ name }'"}) String bad10(Integer id, String name); List good1(Integer id); 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} From 5af1b367c79a1e171b98e600c77f55ea4fd1f5cf Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 10 Oct 2022 14:06:05 +0200 Subject: [PATCH 016/136] Support data extensions --- config/identical-files.json | 5 +++ javascript/ql/lib/qlpack.yml | 2 ++ .../data/internal/ApiGraphModels.qll | 11 ++++++ .../internal/ApiGraphModelsExtensions.qll | 36 +++++++++++++++++++ .../frameworks/data/internal/model.yml | 26 ++++++++++++++ python/ql/lib/qlpack.yml | 4 ++- .../data/internal/ApiGraphModels.qll | 11 ++++++ .../internal/ApiGraphModelsExtensions.qll | 36 +++++++++++++++++++ .../python/frameworks/data/internal/model.yml | 26 ++++++++++++++ .../data/internal/ApiGraphModels.qll | 11 ++++++ .../internal/ApiGraphModelsExtensions.qll | 36 +++++++++++++++++++ .../ruby/frameworks/data/internal/model.yml | 26 ++++++++++++++ ruby/ql/lib/qlpack.yml | 3 ++ 13 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/data/internal/model.yml create mode 100644 python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll create mode 100644 python/ql/lib/semmle/python/frameworks/data/internal/model.yml create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/data/internal/model.yml diff --git a/config/identical-files.json b/config/identical-files.json index 0a5d037e226..2e8c081db23 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -537,6 +537,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/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index c1f80647830..1fd28343800 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/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/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 2cc69948b1d..9387312e1ce 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/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/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 e203b2c8f5d..ce6a37ca986 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 From d8e566a50eeadb3f62c14888c17ef4c48767694e Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 5 Dec 2022 11:17:57 +0100 Subject: [PATCH 017/136] Add data-extension files --- .../javascript/frameworks/minimongo/model.yml | 80 ++ .../javascript/frameworks/mongodb/model.yml | 791 ++++++++++++++++++ .../javascript/frameworks/mssql/model.yml | 39 + .../javascript/frameworks/mysql/model.yml | 70 ++ .../semmle/javascript/frameworks/pg/model.yml | 108 +++ .../javascript/frameworks/sequelize/model.yml | 282 +++++++ .../javascript/frameworks/spanner/model.yml | 189 +++++ .../javascript/frameworks/sqlite3/model.yml | 28 + 8 files changed, 1587 insertions(+) create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/minimongo/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mongodb/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mssql/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mysql/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/pg/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/sequelize/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/spanner/model.yml create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/sqlite3/model.yml 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.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.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.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.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.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.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.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] From fcdb2fa03f25ceaa175d5fb89dff65f668c9a8b1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 5 Dec 2022 15:16:43 +0100 Subject: [PATCH 018/136] JS: Remove MaD models from .qll files --- javascript/ql/lib/javascript.qll | 1 - .../frameworks/ImportGeneratedModels.qll | 12 - .../javascript/frameworks/minimongo/Model.qll | 86 -- .../javascript/frameworks/mongodb/Model.qll | 806 ------------------ .../javascript/frameworks/mssql/Model.qll | 45 - .../javascript/frameworks/mysql/Model.qll | 79 -- .../semmle/javascript/frameworks/pg/Model.qll | 120 --- .../javascript/frameworks/sequelize/Model.qll | 297 ------- .../javascript/frameworks/spanner/Model.qll | 198 ----- .../javascript/frameworks/sqlite3/Model.qll | 37 - 10 files changed, 1681 deletions(-) delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/ImportGeneratedModels.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/minimongo/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mongodb/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mssql/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/mysql/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/pg/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/sequelize/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/spanner/Model.qll delete mode 100644 javascript/ql/lib/semmle/javascript/frameworks/sqlite3/Model.qll 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/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/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/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/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/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/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/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/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/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", // - ] - } -} From b3d838d678d49d60c6f9a3aa08ae09e17b30e628 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 7 Dec 2022 14:45:36 +0000 Subject: [PATCH 019/136] C++: Define the sources more clearly and consistently (fixes performance issue). --- .../CWE/CWE-311/CleartextBufferWrite.ql | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index ec78e6b63fb..d1f54ba0968 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -19,7 +19,30 @@ 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 { + BufferWrite::BufferWrite write; + + SensitiveBufferWrite() { + this = write and + write.getDest() instanceof SensitiveExpr + } + + /** + * Gets a data source of this operation. + */ + Expr getASource() { result = write.getASource() } + + /** + * Gets the destination buffer of this operation. + */ + Expr getDest() { result = write.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,12 +54,12 @@ 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, + ToBufferConfiguration config, SensitiveBufferWrite w, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, FlowSource source, SensitiveExpr dest where config.hasFlowPath(sourceNode, sinkNode) and From 4b8575bfc3ee6c15b5ee8fb050e91945442b28a5 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 7 Dec 2022 15:35:45 +0000 Subject: [PATCH 020/136] C++: Simplify the query slightly. --- cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index d1f54ba0968..1c0320f2576 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -60,12 +60,11 @@ class ToBufferConfiguration extends TaintTracking::Configuration { from ToBufferConfiguration config, SensitiveBufferWrite w, DataFlow::PathNode sourceNode, - DataFlow::PathNode sinkNode, FlowSource source, SensitiveExpr dest + 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() + ")" From 80cd994e362202269be8111255a6f20c9c545819 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Nov 2022 10:32:24 +0000 Subject: [PATCH 021/136] Swift: Add taint reach to SummaryStats.ql. --- swift/ql/src/queries/Summary/SummaryStats.ql | 45 +++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/swift/ql/src/queries/Summary/SummaryStats.ql b/swift/ql/src/queries/Summary/SummaryStats.ql index 0408bead921..e313a96ad29 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.hasFlow(_, 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 From a8b8b54f8de7891673bab4407ac561f93e94475c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 7 Dec 2022 16:44:33 +0000 Subject: [PATCH 022/136] Update cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql Co-authored-by: Mathias Vorreiter Pedersen --- .../Security/CWE/CWE-311/CleartextBufferWrite.ql | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index 1c0320f2576..6858dffbfa8 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -21,23 +21,18 @@ import DataFlow::PathGraph /** * A buffer write into a sensitive expression. */ -class SensitiveBufferWrite extends Expr { - BufferWrite::BufferWrite write; - - SensitiveBufferWrite() { - this = write and - write.getDest() instanceof SensitiveExpr - } +class SensitiveBufferWrite extends Expr instanceof BufferWrite::BufferWrite { + SensitiveBufferWrite() { super.getDest() instanceof SensitiveExpr } /** * Gets a data source of this operation. */ - Expr getASource() { result = write.getASource() } + Expr getASource() { result = super.getASource() } /** * Gets the destination buffer of this operation. */ - Expr getDest() { result = write.getDest() } + Expr getDest() { result = super.getDest() } } /** From 6267da44ae6b5cbfada9835bc2e49db4d16afbf5 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Wed, 7 Dec 2022 18:33:35 +0000 Subject: [PATCH 023/136] Kotlin: Improve diagnostic limit message The message saying that the limit was exceeded is now given at the same severity as the original message. --- .../src/main/kotlin/utils/Logger.kt | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) 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) } } } From 9702ea02fb9d8f6d3cb026c5bc5c3cbb196368de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 20:01:33 +0000 Subject: [PATCH 024/136] JS: Bump patch version of ML-powered library and query packs --- .../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index fb53f54ded7..22249f4b960 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -version: 0.4.2 +version: 0.4.3 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 725beadcb0e..875283e0b63 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.4.2 +version: 0.4.3 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: From d577eeeea8233b47c70ba36fd9b3c977a224f0c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 20:05:30 +0000 Subject: [PATCH 025/136] JS: Bump version of ML-powered library and query packs to 0.4.4 --- .../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index 22249f4b960..3cf9c6bb727 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -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 875283e0b63..bded7e9f770 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.4.3 +version: 0.4.4 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: From 0edfc6e01e8e37da6d8bdadb2551291456906a95 Mon Sep 17 00:00:00 2001 From: retanoj Date: Thu, 8 Dec 2022 09:23:24 +0800 Subject: [PATCH 026/136] greedy matching --- .../Security/CWE/CWE-089/MyBatisCommonLib.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 93831fcdd24..8a7cf318e00 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -135,7 +135,7 @@ predicate isMybatisXmlOrAnnotationSqlInjection( exists(Annotation annotation | unsafeExpression .regexpMatch("\\$\\{\\s*" + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + - "\\b[^}]*?\\}") and + "\\b[^}]*\\}") and annotation.getType() instanceof TypeParam and ma.getAnArgument() = node.asExpr() and annotation.getTarget() = @@ -153,11 +153,11 @@ predicate isMybatisXmlOrAnnotationSqlInjection( exists(int i | not ma.getMethod().getParameter(i).getAnAnnotation().getType() instanceof TypeParam and ( - unsafeExpression.regexpMatch("\\$\\{\\s*param" + (i + 1) + "\\b[^}]*?\\}") + unsafeExpression.regexpMatch("\\$\\{\\s*param" + (i + 1) + "\\b[^}]*\\}") or - unsafeExpression.regexpMatch("\\$\\{\\s*arg" + i + "\\b[^}]*?\\}") + unsafeExpression.regexpMatch("\\$\\{\\s*arg" + i + "\\b[^}]*\\}") or - unsafeExpression.regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*?\\}") + unsafeExpression.regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*\\}") ) and ma.getArgument(i) = node.asExpr() ) @@ -172,7 +172,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.regexpMatch("\\$\\{\\s*" + t.getAField().getName() + "\\b[^}]*?\\}") and + unsafeExpression.regexpMatch("\\$\\{\\s*" + t.getAField().getName() + "\\b[^}]*\\}") and ma.getArgument(i) = node.asExpr() ) or From 0058bf4443f6e5145e00dc9a884f82bc45ebf4cc Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 8 Dec 2022 08:44:29 +0100 Subject: [PATCH 027/136] Swift: add timeout to inetgration tests on macOS --- .github/workflows/swift.yml | 1 + 1 file changed, 1 insertion(+) 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 From f2b99c5fff980c3b00a42cdb73de2a72e9859a88 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 7 Dec 2022 20:24:40 +0100 Subject: [PATCH 028/136] Docs: Update README to mention Python 2 requirement --- docs/codeql/README.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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. From 0d2474bd555cd932e13d9a3e55ec6287b58c8b3a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 11:30:53 +0000 Subject: [PATCH 029/136] Autoformat --- .../Security/CWE/CWE-089/MyBatisCommonLib.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 8a7cf318e00..b6bc910484b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisCommonLib.qll @@ -128,13 +128,14 @@ 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 - .regexpMatch("\\$\\{\\s*" + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + + .regexpMatch("\\$\\{\\s*" + + annotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + "\\b[^}]*\\}") and annotation.getType() instanceof TypeParam and ma.getAnArgument() = node.asExpr() and @@ -157,7 +158,8 @@ predicate isMybatisXmlOrAnnotationSqlInjection( or unsafeExpression.regexpMatch("\\$\\{\\s*arg" + i + "\\b[^}]*\\}") or - unsafeExpression.regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*\\}") + unsafeExpression + .regexpMatch("\\$\\{\\s*" + ma.getMethod().getParameter(i).getName() + "\\b[^}]*\\}") ) and ma.getArgument(i) = node.asExpr() ) From 045e3a2cf39f39682dab8e5a20e4220ee3f04476 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 12:22:50 +0000 Subject: [PATCH 030/136] Kotlin: extract callable modality --- .../src/main/kotlin/KotlinFileExtractor.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 4683731d8e9..1d5720f8c44 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1243,6 +1243,13 @@ open class KotlinFileExtractor( if (f.isSuspend) { addModifiers(id, "suspend") } + if (f.symbol !is IrConstructorSymbol) { + when((f as? IrSimpleFunction)?.modality) { + Modality.ABSTRACT -> addModifiers(id, "abstract") + Modality.FINAL -> addModifiers(id, "final") + else -> Unit + } + } linesOfCode?.linesOfCodeInDeclaration(f, id) From 8789dfb655d562ee22c6231f351d2832ab3a6640 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 12:33:42 +0000 Subject: [PATCH 031/136] Make river-crossing example comply with the CodeQL style guide --- docs/codeql/writing-codeql-queries/river-answer-1-path.ql | 4 ++-- .../writing-codeql-queries/river-answer-2-abstract-class.ql | 4 ++-- .../codeql/writing-codeql-queries/river-answer-3-datatypes.ql | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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..3406e416858 100644 --- a/docs/codeql/writing-codeql-queries/river-answer-1-path.ql +++ b/docs/codeql/writing-codeql-queries/river-answer-1-path.ql @@ -13,7 +13,7 @@ class Cargo extends string { } } - /** One of two shores. */ + /** A shore, named either `Left` or `Right`. */ class Shore extends string { Shore() { this = "Left" or @@ -93,7 +93,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) } From e288b07099a8d52ede156f32d06da3cad7ffa72b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 8 Dec 2022 13:02:58 +0000 Subject: [PATCH 032/136] Update swift/ql/src/queries/Summary/SummaryStats.ql Co-authored-by: Mathias Vorreiter Pedersen --- swift/ql/src/queries/Summary/SummaryStats.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/src/queries/Summary/SummaryStats.ql b/swift/ql/src/queries/Summary/SummaryStats.ql index e313a96ad29..d8a5d6d7f6d 100644 --- a/swift/ql/src/queries/Summary/SummaryStats.ql +++ b/swift/ql/src/queries/Summary/SummaryStats.ql @@ -25,7 +25,7 @@ class TaintReachConfig extends TaintTracking::Configuration { float taintReach() { exists(TaintReachConfig config, int tainted, int total | - tainted = count(DataFlow::Node n | config.hasFlow(_, n)) and + tainted = count(DataFlow::Node n | config.hasFlowTo(n)) and total = count(DataFlow::Node n) and result = (tainted * 1000000.0) / total ) From 5674251839c0e00127541f8d9c34b1d227e2f83c Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 8 Dec 2022 13:03:31 +0000 Subject: [PATCH 033/136] Python: Disable `TarSlipImprov` qhelp --- .../{TarSlipImprov.qhelp => TarSlipImprov.qhelp.disabled} | 1 + 1 file changed, 1 insertion(+) rename python/ql/src/experimental/Security/CWE-022bis/{TarSlipImprov.qhelp => TarSlipImprov.qhelp.disabled} (97%) diff --git a/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp.disabled similarity index 97% rename from python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.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/TarSlipImprov.qhelp +++ b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.qhelp.disabled @@ -1,6 +1,7 @@ + From 37b2b0a1285081430fca61c11eea3e4e12666016 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 13:49:53 +0000 Subject: [PATCH 034/136] Use set literal instead of disjunction --- docs/codeql/writing-codeql-queries/river-answer-1-path.ql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 3406e416858..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,10 +6,7 @@ /** 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"] } } From f35b7f8fe88a1ce43dd1f7a737b0a33a95dd38dc Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 12:05:52 +0100 Subject: [PATCH 035/136] C++: Model `scanf` and `fscanf` as flow sources --- cpp/ql/lib/semmle/code/cpp/models/Models.qll | 2 +- .../implementations/{Sscanf.qll => Scanf.qll} | 54 +++++++++++++++---- .../dataflow/source-sink-tests/local-flow.ql | 16 +++++- .../dataflow/source-sink-tests/remote-flow.ql | 32 +++++++++-- .../source-sink-tests/sources-and-sinks.cpp | 14 +++++ 5 files changed, 101 insertions(+), 17 deletions(-) rename cpp/ql/lib/semmle/code/cpp/models/implementations/{Sscanf.qll => Scanf.qll} (56%) 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/Sscanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll similarity index 56% 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..6773f1bb519 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,40 @@ private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, S ] } } + +/** + * The standard function `scanf` and its assorted variants + */ +private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction { + ScanfModel() { this 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 { + FscanfModel() { this 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/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 11283473802..6968a7738e9 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,17 @@ void test_readv_and_writev(iovec* iovs) { readv(0, iovs, 16); // $ 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 +} From b216c79992c0675ffe98d0db5613ff646237a899 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 15:18:42 +0100 Subject: [PATCH 036/136] C++: Accept test changes --- .../CWE-022/semmle/tests/TaintedPath.expected | 4 +- .../semmle/tests/UnboundedWrite.expected | 40 ------------------- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 2306a3dc384..45ca662513d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -1,7 +1,6 @@ edges | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection | | test.c:31:22:31:25 | argv | test.c:32:11:32:18 | fileName indirection | -| test.c:37:17:37:24 | fileName | test.c:38:11:38:18 | fileName indirection | | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | | test.c:43:17:43:24 | fileName | test.c:44:11:44:18 | fileName indirection | | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | @@ -10,7 +9,6 @@ nodes | test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection | | test.c:31:22:31:25 | argv | semmle.label | argv | | test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection | -| test.c:37:17:37:24 | fileName | semmle.label | fileName | | test.c:37:17:37:24 | scanf output argument | semmle.label | scanf output argument | | test.c:38:11:38:18 | fileName indirection | semmle.label | fileName indirection | | test.c:43:17:43:24 | fileName | semmle.label | fileName | @@ -20,5 +18,5 @@ subpaths #select | test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:9:23:9:26 | argv | user input (argv) | | test.c:32:11:32:18 | fileName | test.c:31:22:31:25 | argv | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:31:22:31:25 | argv | user input (argv) | -| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | fileName | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | fileName | user input (scanf) | +| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | fileName | user input (scanf) | | test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | fileName | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | fileName | user input (scanf) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected index 2c3e9243cf1..170593664f2 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected @@ -7,42 +7,12 @@ edges | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array indirection | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array indirection | -| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 | -| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 | -| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 | -| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 | -| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 indirection | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array indirection | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array indirection | -| tests.c:29:28:29:31 | argv | tests.c:31:15:31:23 | buffer100 | -| tests.c:29:28:29:31 | argv | tests.c:31:15:31:23 | buffer100 | -| tests.c:29:28:29:31 | argv | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:29:28:29:31 | argv | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 | -| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 | -| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:31:15:31:23 | array to pointer conversion | tests.c:31:15:31:23 | buffer100 | -| tests.c:31:15:31:23 | array to pointer conversion | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:31:15:31:23 | array to pointer conversion | tests.c:33:21:33:29 | buffer100 | -| tests.c:31:15:31:23 | array to pointer conversion | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | -| tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 indirection | -| tests.c:31:15:31:23 | buffer100 | tests.c:33:21:33:29 | buffer100 | -| tests.c:31:15:31:23 | buffer100 | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:31:15:31:23 | scanf output argument | tests.c:33:21:33:29 | buffer100 | -| tests.c:31:15:31:23 | scanf output argument | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:33:21:33:29 | array to pointer conversion | tests.c:33:21:33:29 | buffer100 | -| tests.c:33:21:33:29 | array to pointer conversion | tests.c:33:21:33:29 | buffer100 indirection | -| tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | -| tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 indirection | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | @@ -65,16 +35,11 @@ nodes | tests.c:29:28:29:34 | access to array | semmle.label | access to array | | tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection | | tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | -| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | -| tests.c:31:15:31:23 | buffer100 indirection | semmle.label | buffer100 indirection | -| tests.c:31:15:31:23 | scanf output argument | semmle.label | scanf output argument | -| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | -| tests.c:33:21:33:29 | buffer100 indirection | semmle.label | buffer100 indirection | | tests.c:34:10:34:13 | argv | semmle.label | argv | | tests.c:34:10:34:13 | argv | semmle.label | argv | | tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | @@ -84,11 +49,6 @@ nodes #select | tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | | tests.c:29:3:29:9 | call to sprintf | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | -| tests.c:31:15:31:23 | buffer100 | tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | -| tests.c:31:15:31:23 | buffer100 | tests.c:29:28:29:31 | argv | tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | | tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | -| tests.c:33:21:33:29 | buffer100 | tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | -| tests.c:33:21:33:29 | buffer100 | tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | -| tests.c:33:21:33:29 | buffer100 | tests.c:31:15:31:23 | buffer100 | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | | tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 | | tests.c:34:25:34:33 | buffer100 | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv | From 33fa76f91122fd9a811be4d11ba0046acd0aa366 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 15:20:54 +0100 Subject: [PATCH 037/136] C++: Add change note --- cpp/ql/lib/change-notes/2022-12-08-support-scanf-dataflow.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2022-12-08-support-scanf-dataflow.md 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. From a79126268ca3710480ae7ac3643a7fb87c0d8c53 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 14:39:57 +0000 Subject: [PATCH 038/136] Override modality when needed In particular when generating an implementation based on an abstract prototype, the result is final, and an interface forwarder is open / Java's default modality. --- .../src/main/kotlin/KotlinFileExtractor.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 1d5720f8c44..10d1db8787a 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -891,7 +891,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, 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) @@ -1244,7 +1244,7 @@ open class KotlinFileExtractor( addModifiers(id, "suspend") } if (f.symbol !is IrConstructorSymbol) { - when((f as? IrSimpleFunction)?.modality) { + when(overriddenAttributes?.modality ?: (f as? IrSimpleFunction)?.modality) { Modality.ABSTRACT -> addModifiers(id, "abstract") Modality.FINAL -> addModifiers(id, "final") else -> Unit @@ -5311,7 +5311,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, typeSub, classTypeArgs, overriddenAttributes = OverriddenFunctionAttributes(id = ids.function, sourceLoc = tw.getLocation(e), modality = Modality.FINAL)) addModifiers(ids.function, "override") if (st.isSuspendFunctionOrKFunction()) { @@ -5536,6 +5536,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? { From d0a2c1c9b6ab5d2947c8af9c7856593f21da6c46 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 14:44:43 +0000 Subject: [PATCH 039/136] Accept test changes --- .../library-tests/exprs/funcExprs.expected | 140 +++++++++--------- .../visibility.expected | 4 + .../library-tests/methods/methods.expected | 76 +++++----- 3 files changed, 112 insertions(+), 108 deletions(-) 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/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/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index 6a86ea6bf5b..a4d394362fc 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -1,59 +1,59 @@ 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:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | final, public, static | | +| methods3.kt:5:1:7:1 | Class3 | methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | final, public | | +| 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() | From 1ba8b6d35a7ae480c4a91c099dd52f02199fab54 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 8 Dec 2022 15:57:57 +0100 Subject: [PATCH 040/136] Swift: fix extraction of sources from `..` --- swift/extractor/SwiftExtractor.cpp | 24 ++++++++----------- swift/extractor/infra/Path.h | 7 ------ .../infra/SwiftLocationExtractor.cpp | 6 ++--- swift/extractor/infra/{ => file}/Path.cpp | 6 ++--- swift/extractor/infra/file/Path.h | 7 ++++++ .../frontend-invocations/Files.expected | 1 + .../posix-only/frontend-invocations/G.swift | 0 .../posix-only/frontend-invocations/build.sh | 1 + 8 files changed, 25 insertions(+), 27 deletions(-) delete mode 100644 swift/extractor/infra/Path.h rename swift/extractor/infra/{ => file}/Path.cpp (87%) create mode 100644 swift/extractor/infra/file/Path.h create mode 100644 swift/integration-tests/posix-only/frontend-invocations/G.swift 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 ) From cbf722dad0931bf5b32f74af3c9db39b46b0f6e1 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 8 Dec 2022 15:59:41 +0100 Subject: [PATCH 041/136] Ruby: Add `SummarizedCallable::getParameter` --- .../lib/codeql/ruby/dataflow/FlowSummary.qll | 13 ++++++++++++ .../internal/FlowSummaryImplSpecific.qll | 21 +++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) 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/FlowSummaryImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll index 0fde6438872..615578f8891 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll @@ -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. */ From 8600d2d12decc85a053cbb7c2ac3e79d2fc5e1e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Dec 2022 15:01:05 +0000 Subject: [PATCH 042/136] Bump Newtonsoft.Json in /csharp/autobuilder/Semmle.Autobuild.CSharp Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 13.0.1 to 13.0.2. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/13.0.1...13.0.2) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ - + From 8f9a73ee097aee409678f552358a09084c55242f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 16:14:12 +0100 Subject: [PATCH 043/136] C++: Address review comments --- .../lib/semmle/code/cpp/models/implementations/Scanf.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll index 6773f1bb519..079a231a913 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll @@ -71,9 +71,7 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, /** * The standard function `scanf` and its assorted variants */ -private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction { - ScanfModel() { this instanceof Scanf } - +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() @@ -83,9 +81,7 @@ private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction { /** * The standard function `fscanf` and its assorted variants */ -private class FscanfModel extends ScanfFunctionModel, RemoteFlowSourceFunction { - FscanfModel() { this instanceof Fscanf } - +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() From 935e264f2472cbc6a58aee4c35821d0456d66a48 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 8 Dec 2022 17:04:32 +0100 Subject: [PATCH 044/136] Swift: add empty directory marker --- .../integration-tests/posix-only/frontend-invocations/dir/.empty | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 swift/integration-tests/posix-only/frontend-invocations/dir/.empty 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 From 7645d4d92802b38f7614fc5f3270aee88c03c431 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 8 Dec 2022 17:31:48 +0100 Subject: [PATCH 045/136] Swift: remove `ModuleDecl` from `PrintAst` test --- swift/ql/test/library-tests/ast/PrintAst.expected | 6 ------ swift/ql/test/library-tests/ast/PrintAst.ql | 4 +++- 2 files changed, 3 insertions(+), 7 deletions(-) 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 + } } From ec0ce56269ef879e56face2f0e01d8419d1fdeac Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 19:20:11 +0100 Subject: [PATCH 046/136] C++: Model `getaddrinfo` as flow source --- .../code/cpp/models/implementations/Inet.qll | 19 +++++++++++++++++++ .../source-sink-tests/sources-and-sinks.cpp | 10 ++++++++++ 2 files changed, 29 insertions(+) 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..5e42d96ca33 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll @@ -1,6 +1,7 @@ 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") } @@ -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() { 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/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 6968a7738e9..fcc4ee0a315 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 @@ -40,3 +40,13 @@ void test_scanf(FILE *stream, int *d, char *buf) { 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 +} From aabbafd2bf5ee3bc03362f89ef32271c9700efdb Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 19:33:11 +0100 Subject: [PATCH 047/136] C++: Fix QL-for-QL warning --- .../code/cpp/models/implementations/Inet.qll | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 5e42d96ca33..2589c6f46a4 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll @@ -4,7 +4,7 @@ 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 @@ -13,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 @@ -33,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 @@ -52,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 @@ -65,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) { ( @@ -77,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 @@ -86,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 @@ -95,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) { ( @@ -115,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 @@ -128,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) { ( @@ -145,7 +145,7 @@ private class Gethostbyaddr extends TaintFunction, ArrayFunction { } private class Getaddrinfo extends TaintFunction, ArrayFunction, RemoteFlowSourceFunction { - Getaddrinfo() { hasGlobalName("getaddrinfo") } + Getaddrinfo() { this.hasGlobalName("getaddrinfo") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref([0 .. 2]) and From 2095f11b8cece2c7440c9a06740e148260530c61 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 8 Dec 2022 23:35:32 +0100 Subject: [PATCH 048/136] C++: Add change note --- .../change-notes/2022-12-08-support-getaddrinfo-dataflow.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2022-12-08-support-getaddrinfo-dataflow.md 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. From 1d209d1bcd5f815a15e8acd66e791c38c24805a8 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 8 Dec 2022 22:52:40 +0000 Subject: [PATCH 049/136] Accept modifiers test changes --- .../library-tests/modifiers/modifiers.expected | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 | From 6822399dbba8db89e701c35a010abc4cba763880 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 9 Dec 2022 09:17:00 +0100 Subject: [PATCH 050/136] Swift: Rename NSData.qll to NsData.qll --- swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll | 2 +- .../swift/frameworks/StandardLibrary/{NSData.qll => NsData.qll} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename swift/ql/lib/codeql/swift/frameworks/StandardLibrary/{NSData.qll => NsData.qll} (100%) 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/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 From 43f23801f563423358e4065af20324078088bffb Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 10:08:01 +0100 Subject: [PATCH 051/136] Kotlin: Add test for extension `$default` functions --- .../library-tests/methods/exprs.expected | 47 ++++++++++++++++--- .../library-tests/methods/methods.expected | 13 +++-- .../kotlin/library-tests/methods/methods.ql | 9 ++++ .../kotlin/library-tests/methods/methods3.kt | 4 +- .../library-tests/methods/parameters.expected | 17 +++++-- 5 files changed, 74 insertions(+), 16 deletions(-) diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 99315e33359..95e970fce23 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 | p0 | VarAccess | +| 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: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 | p1 | 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: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/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index a4d394362fc..bd7d00a8671 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -38,8 +38,10 @@ methods | 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) | 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:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | final, public, static | | -| methods3.kt:5:1:7:1 | Class3 | methods3.kt:6:5:6:46 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(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(java.lang.String,foo.bar.Class3,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 | | @@ -74,6 +76,9 @@ 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:6:5:6:45 | fooBarMethodExt | 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 +| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | +| methods3.kt:6:5:6:45 | fooBarMethodExt | methods3.kt:6:5:6:45 | fooBarMethodExt$default | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.ql b/java/ql/test/kotlin/library-tests/methods/methods.ql index 365d41ff1ee..bbde7bfc6e6 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.ql +++ b/java/ql/test/kotlin/library-tests/methods/methods.ql @@ -17,3 +17,12 @@ 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 + ) +} 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 | From 6457e059f5051d9a068b8892dbfcce83899c6ae6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 10:09:37 +0100 Subject: [PATCH 052/136] Kotlin: Fix extraction of `$default` extension functions --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 4 ++++ java/ql/test/kotlin/library-tests/methods/exprs.expected | 4 ++-- java/ql/test/kotlin/library-tests/methods/methods.expected | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 10d1db8787a..c1357feca37 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -975,6 +975,10 @@ 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 extendedType = allParamTypeResults[0] // TODO: this is not correct for member extension methods, where the dispatch receiver is the first parameter + tw.writeKtExtensionFunctions(methodId, extendedType.javaResult.id, extendedType.kotlinResult.id) + } } tw.writeHasLocation(id, locId) if (f.visibility != DescriptorVisibilities.PRIVATE && f.visibility != DescriptorVisibilities.PRIVATE_TO_THIS) { diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 95e970fce23..215c0e7d7e3 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -306,10 +306,10 @@ | 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 | p0 | VarAccess | | 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 | @@ -326,11 +326,11 @@ | 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 | p1 | 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 | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index bd7d00a8671..7cd7e92c37d 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -77,8 +77,8 @@ constructors | methods.kt:5:1:20:1 | Class | methods.kt:5:1:20:1 | Class | Class() | extensions | 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 -| methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt | methods3.kt:3:1:3:49 | fooBarTopLevelMethodExt$default | -| methods3.kt:6:5:6:45 | fooBarMethodExt | methods3.kt:6:5:6:45 | fooBarMethodExt$default | From d93dce0fa9fd99a8aa3ebe6fa13240f00e81d1cb Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 12:24:41 +0100 Subject: [PATCH 053/136] Kotlin: Fix extension and dispatch parameter order in `$default` functions --- .../src/main/kotlin/KotlinFileExtractor.kt | 32 ++++++++-------- java/ql/lib/semmle/code/java/Expr.qll | 3 +- java/ql/lib/semmle/code/java/Member.qll | 29 ++++++++------ java/ql/lib/semmle/code/java/Variable.qll | 2 +- .../library-tests/methods/exprs.expected | 2 +- .../library-tests/methods/methods.expected | 8 +++- .../kotlin/library-tests/methods/methods.ql | 7 ++++ .../parameter-defaults/PrintAst.expected | 38 +++++++++---------- 8 files changed, 71 insertions(+), 50 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index c1357feca37..d397c9b5022 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -957,7 +957,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 { @@ -976,7 +976,8 @@ open class KotlinFileExtractor( extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = extractMethodAndParameterTypeAccesses) addModifiers(id, "static") if (extReceiver != null) { - val extendedType = allParamTypeResults[0] // TODO: this is not correct for member extension methods, where the dispatch receiver is the first parameter + val idx = if (dispatchReceiver != null) 1 else 0 + val extendedType = allParamTypeResults[idx] tw.writeKtExtensionFunctions(methodId, extendedType.javaResult.id, extendedType.kotlinResult.id) } } @@ -1044,8 +1045,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) @@ -1188,6 +1189,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) @@ -1797,11 +1799,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) } @@ -1820,17 +1823,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, @@ -1890,13 +1892,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) } @@ -4050,8 +4053,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 } 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..d0e7de8a9ac 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 getExtensionParameterIndex() { + 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/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll index 7be49acf546..75c7501c8a7 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).getExtensionParameterIndex() } /** diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 215c0e7d7e3..5de17a12bf9 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -326,7 +326,7 @@ | 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 | p1 | VarAccess | +| 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 | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index 7cd7e92c37d..89cdd03f303 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -41,7 +41,7 @@ methods | 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(java.lang.String,foo.bar.Class3,int,int,java.lang.Object) | public, static | Compiler generated | +| 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 | | @@ -82,3 +82,9 @@ extensions | 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 bbde7bfc6e6..7042cfd48cf 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.ql +++ b/java/ql/test/kotlin/library-tests/methods/methods.ql @@ -26,3 +26,10 @@ query predicate extensionsMismatch(Method src, Method def) { def instanceof ExtensionMethod and not src instanceof ExtensionMethod ) } + +query predicate extensionIndex(ExtensionMethod m, int i, Type t) { + m.fromSource() and + m.getExtensionParameterIndex() = i and + m.getExtendedType() = t and + m.getParameter(i).getType() = t +} 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..0fe95582369 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 @@ -729,13 +729,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 +759,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 +773,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 +787,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 +797,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 From ac5219fc7af1e94b69aa9290cc9adf55c0c16c14 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 12:34:44 +0100 Subject: [PATCH 054/136] Kotlin: Adjust `ExtensionReceiverAccess.toString` to not return hard coded `this` value --- java/ql/lib/semmle/code/java/Expr.qll | 12 +++++++----- .../test/kotlin/library-tests/methods/exprs.expected | 4 ++-- .../parameter-defaults/PrintAst.expected | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index a10da9ecc9f..0e1b88a3a83 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1894,16 +1894,18 @@ class VarAccess extends Expr, @varaccess { * An access to an extension receiver parameter. This is a parameter access that takes the form of `this` in Kotlin. */ class ExtensionReceiverAccess extends VarAccess { + Parameter p; + ExtensionReceiverAccess() { - exists(Parameter p | - this.getVariable() = p and - p.isExtensionParameter() - ) + this.getVariable() = p and + p.isExtensionParameter() } override string getAPrimaryQlClass() { result = "ExtensionReceiverAccess" } - override string toString() { result = "this" } + override string toString() { + if p.getName() = "" then result = "this" else result = p.getName() + } } /** diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 5de17a12bf9..f0474cd40fd 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -306,10 +306,10 @@ | 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 | p0 | ExtensionReceiverAccess | | 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 | @@ -327,10 +327,10 @@ | 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 | p1 | ExtensionReceiverAccess | | 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 | 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 0fe95582369..ae6e420be31 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -566,7 +566,7 @@ test.kt: # 19| 2: [ReturnStmt] return ... # 19| 0: [MethodAccess] f(...) # 19| -1: [VarAccess] p0 -# 19| 0: [ExtensionReceiverAccess] this +# 19| 0: [ExtensionReceiverAccess] p1 # 19| 1: [VarAccess] p2 # 19| 2: [VarAccess] p3 # 19| 3: [VarAccess] p4 @@ -774,7 +774,7 @@ test.kt: # 56| 2: [ReturnStmt] return ... # 56| 0: [MethodAccess] test(...) # 56| -1: [VarAccess] p0 -# 56| 0: [ExtensionReceiverAccess] this +# 56| 0: [ExtensionReceiverAccess] p1 # 56| 1: [VarAccess] p2 # 56| 2: [VarAccess] p3 # 56| 3: [VarAccess] p4 From f646938d919668b633d29103abf65c43d504f822 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 13:15:25 +0100 Subject: [PATCH 055/136] Revert "Kotlin: Adjust `ExtensionReceiverAccess.toString` to not return hard coded `this` value" This reverts commit 9649a8f64aa47d860d3ce2d005a939df75ee0e41. --- java/ql/lib/semmle/code/java/Expr.qll | 12 +++++------- .../test/kotlin/library-tests/methods/exprs.expected | 4 ++-- .../parameter-defaults/PrintAst.expected | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 0e1b88a3a83..a10da9ecc9f 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1894,18 +1894,16 @@ class VarAccess extends Expr, @varaccess { * An access to an extension receiver parameter. This is a parameter access that takes the form of `this` in Kotlin. */ class ExtensionReceiverAccess extends VarAccess { - Parameter p; - ExtensionReceiverAccess() { - this.getVariable() = p and - p.isExtensionParameter() + exists(Parameter p | + this.getVariable() = p and + p.isExtensionParameter() + ) } override string getAPrimaryQlClass() { result = "ExtensionReceiverAccess" } - override string toString() { - if p.getName() = "" then result = "this" else result = p.getName() - } + override string toString() { result = "this" } } /** diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index f0474cd40fd..5de17a12bf9 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -306,10 +306,10 @@ | 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 | p0 | ExtensionReceiverAccess | | 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 | @@ -327,10 +327,10 @@ | 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 | p1 | ExtensionReceiverAccess | | 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 | 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 ae6e420be31..0fe95582369 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -566,7 +566,7 @@ test.kt: # 19| 2: [ReturnStmt] return ... # 19| 0: [MethodAccess] f(...) # 19| -1: [VarAccess] p0 -# 19| 0: [ExtensionReceiverAccess] p1 +# 19| 0: [ExtensionReceiverAccess] this # 19| 1: [VarAccess] p2 # 19| 2: [VarAccess] p3 # 19| 3: [VarAccess] p4 @@ -774,7 +774,7 @@ test.kt: # 56| 2: [ReturnStmt] return ... # 56| 0: [MethodAccess] test(...) # 56| -1: [VarAccess] p0 -# 56| 0: [ExtensionReceiverAccess] p1 +# 56| 0: [ExtensionReceiverAccess] this # 56| 1: [VarAccess] p2 # 56| 2: [VarAccess] p3 # 56| 3: [VarAccess] p4 From 81c35c8b278b4729ebe80fa2a64dcadefec40298 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 13:28:10 +0100 Subject: [PATCH 056/136] Adjust `PathSanitizer` to use fixed `$default` extension method functionality --- .../ql/lib/semmle/code/java/security/PathSanitizer.qll | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll index 061ec5dc68c..775b3828a67 100644 --- a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll +++ b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll @@ -298,8 +298,8 @@ 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).getExtensionParameterIndex()) else result = ma.getQualifier() } @@ -310,8 +310,10 @@ 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).getExtensionParameterIndex() + 1) else result = ma.getArgument(argPos) } From 243c311b3d6240095461aa0b9a10dd09b8be6260 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 15:18:57 +0100 Subject: [PATCH 057/136] Accept unit test changes --- .../jvmoverloads-annotation/PrintAst.expected | 22 +++++++++---------- .../jvmoverloads-annotation/test.expected | 2 +- .../reflection/PrintAst.expected | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) 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..439613f6dd4 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected @@ -72,7 +72,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 +116,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 @@ -356,9 +356,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 +383,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 @@ -411,13 +411,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 +456,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 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/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 From ce5509a080339f9f23ddfe5920a53f249ccca7b6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Dec 2022 15:57:47 +0100 Subject: [PATCH 058/136] Kotlin: Adjust MaD argument shifting for `$default` method --- .../java/dataflow/internal/FlowSummaryImplSpecific.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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..3f44d635a68 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 ) ) From e410e2744bdefd7751585ce69cd082847cf3991e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 9 Dec 2022 08:46:08 +0100 Subject: [PATCH 059/136] Add change note --- .../lib/change-notes/2022-12-09-default-extension-methods.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2022-12-09-default-extension-methods.md 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..f9335b2670d --- /dev/null +++ b/java/ql/lib/change-notes/2022-12-09-default-extension-methods.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The extraction of extension methods have been improved when default parameter values are present. The dispatch and extension receiver parameters are extracted in the correct order. The `ExtensionMethod::getExtensionParameterIndex` predicate has been introduced to facilitate getting the correct extension parameter index. From 6bcfdfca88409b9c1d12d293da4f3edb1ce4820d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 9 Dec 2022 10:23:54 +0100 Subject: [PATCH 060/136] Adjust `getExtensionReceiverParameterIndex` predicate name and change note --- .../change-notes/2022-12-09-default-extension-methods.md | 2 +- java/ql/lib/semmle/code/java/Member.qll | 2 +- java/ql/lib/semmle/code/java/Variable.qll | 2 +- java/ql/lib/semmle/code/java/security/PathSanitizer.qll | 6 ++++-- java/ql/test/kotlin/library-tests/methods/methods.ql | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) 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 index f9335b2670d..df9d23503da 100644 --- 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 @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -* The extraction of extension methods have been improved when default parameter values are present. The dispatch and extension receiver parameters are extracted in the correct order. The `ExtensionMethod::getExtensionParameterIndex` predicate has been introduced to facilitate getting the correct extension parameter index. +* 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/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index d0e7de8a9ac..d55a0eefdec 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -820,7 +820,7 @@ class ExtensionMethod extends Method { * extension methods that are defined as members, the index is 1. Index 0 is the dispatch receiver of the `$default` * method. */ - int getExtensionParameterIndex() { + int getExtensionReceiverParameterIndex() { if exists(Method src | this = src.getKotlinParameterDefaultsProxy() and diff --git a/java/ql/lib/semmle/code/java/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll index 75c7501c8a7..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() = this.getCallable().(ExtensionMethod).getExtensionParameterIndex() + this.getPosition() = this.getCallable().(ExtensionMethod).getExtensionReceiverParameterIndex() } /** diff --git a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll index 775b3828a67..14445971b47 100644 --- a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll +++ b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll @@ -299,7 +299,8 @@ private class PathNormalizeSanitizer extends MethodAccess { */ private Expr getVisualQualifier(MethodAccess ma) { if ma.getMethod() instanceof ExtensionMethod - then result = ma.getArgument(ma.getMethod().(ExtensionMethod).getExtensionParameterIndex()) + then + result = ma.getArgument(ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex()) else result = ma.getQualifier() } @@ -313,7 +314,8 @@ private Argument getVisualArgument(MethodAccess ma, int argPos) { if ma.getMethod() instanceof ExtensionMethod then result = - ma.getArgument(argPos + ma.getMethod().(ExtensionMethod).getExtensionParameterIndex() + 1) + ma.getArgument(argPos + ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex() + + 1) else result = ma.getArgument(argPos) } diff --git a/java/ql/test/kotlin/library-tests/methods/methods.ql b/java/ql/test/kotlin/library-tests/methods/methods.ql index 7042cfd48cf..0f0b43f4e4b 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.ql +++ b/java/ql/test/kotlin/library-tests/methods/methods.ql @@ -29,7 +29,7 @@ query predicate extensionsMismatch(Method src, Method def) { query predicate extensionIndex(ExtensionMethod m, int i, Type t) { m.fromSource() and - m.getExtensionParameterIndex() = i and + m.getExtensionReceiverParameterIndex() = i and m.getExtendedType() = t and m.getParameter(i).getType() = t } From 9fa840106fd9fda143e131782086e017669fc4d3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 11 Apr 2022 15:30:36 +0200 Subject: [PATCH 061/136] Extract annotation declarations --- .../src/main/kotlin/KotlinFileExtractor.kt | 22 ++++++-- .../annotation_classes/PrintAst.expected | 55 +++++++++++++++++++ .../annotation_classes/PrintAst.qlref | 1 + .../annotation_classes/classes.expected | 17 +++++- .../annotation_classes/classes.ql | 4 ++ .../library-tests/annotation_classes/def.kt | 15 ++++- .../library-tests/annotation_classes/use.java | 11 +++- 7 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.qlref diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 10d1db8787a..e5648bf9965 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -470,6 +470,10 @@ open class KotlinFileExtractor( if (c.isInterfaceLike) { val interfaceId = id.cast() tw.writeInterfaces(interfaceId, cls, pkgId, interfaceId) + + if (kind == ClassKind.ANNOTATION_CLASS) { + tw.writeIsAnnotType(interfaceId) + } } else { val classId = id.cast() tw.writeClasses(classId, cls, pkgId, classId) @@ -495,10 +499,20 @@ 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 (kind == ClassKind.ANNOTATION_CLASS) { + c.declarations + .filterIsInstance() + .map { + val getter = it.getter!! + val label = extractFunction(getter, id, false, null, listOf()) + tw.writeIsAnnotElem(label!!.cast()) + } + } else { + c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) } + if (extractStaticInitializer) + extractStaticInitializer(c, { id }) + extractJvmStaticProxyMethods(c, id, extractPrivateMembers, extractFunctionBodies) + } } if (c.isNonCompanionObject) { // For `object MyObject { ... }`, the .class has an 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..321512a036f --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -0,0 +1,55 @@ +def.kt: +# 0| [CompilationUnit] def +# 0| 1: [Class] DefKt +# 13| 1: [Method] fn +#-----| 4: (Parameters) +# 13| 0: [Parameter] a +# 13| 5: [BlockStmt] { ... } +# 14| 0: [ExprStmt] ; +# 14| 0: [MethodAccess] println(...) +# 14| -1: [TypeAccess] ConsoleKt +# 14| 0: [MethodAccess] abc(...) +# 14| -1: [VarAccess] a +# 1| 2: [Interface] SomeAnnotation +#-----| -3: (Annotations) +# 1| 1: [Method] abc +#-----| 1: (Annotations) +# 1| 2: [Method] y +# 3| 3: [Interface] ReplaceWith +# 3| 1: [Method] expression +# 5| 4: [Interface] Deprecated +# 6| 1: [Method] message +# 7| 2: [Method] replaceWith +# 9| 5: [Class] X +# 11| 1: [Constructor] X +# 9| 5: [BlockStmt] { ... } +# 9| 0: [SuperConstructorInvocationStmt] super(...) +# 11| 1: [BlockStmt] { ... } +use.java: +# 0| [CompilationUnit] use +# 2| 1: [Class] use +#-----| -1: (Base Types) +# 2| 0: [TypeAccess] SomeAnnotation +# 4| 2: [Method] abc +#-----| 1: (Annotations) +# 3| 1: [Annotation] Override +# 4| 3: [TypeAccess] int +# 4| 5: [BlockStmt] { ... } +# 4| 0: [ReturnStmt] return ... +# 4| 0: [IntegerLiteral] 1 +# 6| 3: [Method] y +#-----| 1: (Annotations) +# 5| 1: [Annotation] Override +# 6| 3: [TypeAccess] String +# 6| 5: [BlockStmt] { ... } +# 6| 0: [ReturnStmt] return ... +# 6| 0: [StringLiteral] "" +# 9| 4: [Method] annotationType +#-----| 1: (Annotations) +# 8| 1: [Annotation] Override +# 9| 3: [TypeAccess] Class +# 9| 0: [WildcardTypeAccess] ? ... +# 9| 0: [TypeAccess] Annotation +# 9| 5: [BlockStmt] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [NullLiteral] null 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..e31fd25502f 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,15 @@ -| def.kt:2:1:2:31 | SomeAnnotation | Interface | -| use.java:2:23:2:25 | use | Class | +annotation +| def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:53:1:66 | abc | +| def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:69:1:86 | y | +| def.kt:3:1:3:52 | ReplaceWith | def.kt:3:30:3:51 | expression | +| def.kt:5:1:7:51 | Deprecated | def.kt:6:5:6:23 | message | +| def.kt:5:1:7:51 | Deprecated | def.kt:7:5:7:50 | replaceWith | +| file:///modules/java.base/java/lang/annotation/Retention.class:0:0:0:0 | Retention | file:///modules/java.base/java/lang/annotation/Retention.class:0:0:0:0 | value | +| file:///modules/java.base/java/lang/annotation/Target.class:0:0:0:0 | Target | file:///modules/java.base/java/lang/annotation/Target.class:0:0:0:0 | value | +#select +| def.kt:0:0:0:0 | DefKt | Class | +| def.kt:1:1:1:87 | SomeAnnotation | Interface | +| def.kt:3:1:3:52 | ReplaceWith | Interface | +| def.kt:5:1:7:51 | Deprecated | Interface | +| def.kt:9:1:11:7 | X | Class | +| use.java:2:14:2:16 | use | 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..44582d74e53 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,7 @@ import java from ClassOrInterface x where x.fromSource() select x, x.getPrimaryQlClasses() + +query predicate annotation(AnnotationType at, AnnotationElement ae) { + at.getAnAnnotationElement() = ae +} 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..132fceb4244 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,16 @@ +annotation class SomeAnnotation(@get:JvmName("abc") val x: Int = 5, val y: String = "") -annotation class SomeAnnotation +annotation class ReplaceWith(val expression: String) + +annotation class Deprecated( + val message: String, + val replaceWith: ReplaceWith = ReplaceWith("")) + +@Deprecated("This class is deprecated", ReplaceWith("Y")) +@SomeAnnotation(y = "a") +class X + +fun fn(a: SomeAnnotation) { + println(a.x) +} 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..9b9191b849f 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,12 @@ -public abstract class use implements SomeAnnotation {} +public class use implements SomeAnnotation { + @Override + public int abc() { return 1; } + @Override + public String y() { return ""; } + @Override + public Class annotationType() { + return null; + } +} From 7b075c21903aa8dfa0a23b6898c77ec9a9f88266 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 12 Apr 2022 08:43:58 +0200 Subject: [PATCH 062/136] WIP: extract annotations on classes, with constant values --- .../src/main/kotlin/KotlinFileExtractor.kt | 209 ++++++++++++------ java/ql/lib/semmle/code/java/Annotation.qll | 2 +- .../lib/semmle/code/java/DependencyCounts.qll | 2 +- .../CONSISTENCY/children.expected | 1 + .../annotation_classes/PrintAst.expected | 6 + .../annotation_classes/classes.expected | 11 +- .../annotation_classes/classes.ql | 13 +- 7 files changed, 165 insertions(+), 79 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index e5648bf9965..abed6dc7b7a 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -457,7 +457,54 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - val jvmStaticFqName = FqName("kotlin.jvm.JvmStatic") + fun extractAnnotations(c: IrClass): Int { + var count = 0 + for (constructorCall: IrConstructorCall in c.annotations) { + + // todo: do not extract JvmName, what else? + + val t = useType(constructorCall.type) + val annotated = useClassSource(c) + + val id = tw.getLabelFor("@\"annotation;{$annotated};{${t.javaResult.id}}\"") + tw.writeExprs_declannotation(id, t.javaResult.id, annotated, count++) + 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().firstOrNull { it.name == param.name } + if (prop == null) { + continue + } + + val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression + + when (v) { + is IrConst<*> -> { + val exprId = extractConstant(v, id, i) + if (exprId != null) { + + tw.writeAnnotValue(id, useFunction(prop.getter!!), exprId) + } + } + /* + Integer types; + Enum types; + String type; + Classes; + Other annotation types; + Arrays of any type listed above. + */ + + } + } + } + + return count + } fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label { with("class source", c) { @@ -540,6 +587,8 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(c, id) + extractAnnotations(c) + if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) @@ -548,6 +597,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: @@ -3457,13 +3508,6 @@ open class KotlinFileExtractor( 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) { @@ -3614,71 +3658,10 @@ 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) - } + val id = extractConstant(e, exprParent.parent, exprParent.idx) + if (id != null) { + tw.writeCallableEnclosingExpr(id, callable) + tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt) } } is IrGetValue -> { @@ -4170,6 +4153,86 @@ open class KotlinFileExtractor( extractExpressionExpr(loop.condition, callable, id, 0, id) } + // 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 + ): Label? { + 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) + } + } + } + private fun IrValueParameter.isExtensionReceiver(): Boolean { val parentFun = parent as? IrFunction ?: return false return parentFun.extensionReceiverParameter == this diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 28f994053a2..dd6762776c6 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -249,7 +249,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/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected new file mode 100644 index 00000000000..28e24b18b44 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected @@ -0,0 +1 @@ +| file:///modules/java.base/java/util/Random.class:0:0:0:0 | RandomGeneratorProperties | Annotation | 1 | gap | 0, 2, 3, 4, 5 | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 321512a036f..2d34788a76e 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -21,6 +21,12 @@ def.kt: # 6| 1: [Method] message # 7| 2: [Method] replaceWith # 9| 5: [Class] X +#-----| -3: (Annotations) +# 9| 1: [Annotation] Deprecated +# 0| 1: [StringLiteral] This class is deprecated +# 10| 2: [Annotation] SomeAnnotation +# 0| 1: [IntegerLiteral] 5 +# 0| 1: [StringLiteral] a # 11| 1: [Constructor] X # 9| 5: [BlockStmt] { ... } # 9| 0: [SuperConstructorInvocationStmt] super(...) 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 e31fd25502f..824dd2d6d21 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -1,11 +1,16 @@ -annotation +annotationDeclarations | def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:53:1:66 | abc | | def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:69:1:86 | y | | def.kt:3:1:3:52 | ReplaceWith | def.kt:3:30:3:51 | expression | | def.kt:5:1:7:51 | Deprecated | def.kt:6:5:6:23 | message | | def.kt:5:1:7:51 | Deprecated | def.kt:7:5:7:50 | replaceWith | -| file:///modules/java.base/java/lang/annotation/Retention.class:0:0:0:0 | Retention | file:///modules/java.base/java/lang/annotation/Retention.class:0:0:0:0 | value | -| file:///modules/java.base/java/lang/annotation/Target.class:0:0:0:0 | Target | file:///modules/java.base/java/lang/annotation/Target.class:0:0:0:0 | value | +annotations +| def.kt:9:1:9:57 | Deprecated | def.kt:9:1:11:7 | X | def.kt:5:1:7:51 | Deprecated | +| def.kt:10:1:10:24 | SomeAnnotation | def.kt:9:1:11:7 | X | def.kt:1:1:1:87 | SomeAnnotation | +annotationValues +| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | This class is deprecated | +| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | 5 | +| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | a | #select | def.kt:0:0:0:0 | DefKt | Class | | def.kt:1:1:1:87 | SomeAnnotation | Interface | 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 44582d74e53..fc3db6f0c02 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql @@ -4,6 +4,17 @@ from ClassOrInterface x where x.fromSource() select x, x.getPrimaryQlClasses() -query predicate annotation(AnnotationType at, AnnotationElement ae) { +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.getAValue() = v and v.getFile().isSourceFile() +} From 3b09cb2224fba186f8b5ca8731b9d979121ebbcb Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 12 Apr 2022 16:03:21 +0200 Subject: [PATCH 063/136] WIP: Extract annotation values (tests are missing) --- .../src/main/kotlin/KotlinFileExtractor.kt | 210 ++++++++++++------ java/ql/consistency-queries/cfgDeadEnds.ql | 2 + .../CONSISTENCY/children.expected | 1 - .../annotation_classes/PrintAst.expected | 55 +++-- .../annotation_classes/classes.expected | 12 +- .../library-tests/annotation_classes/use.java | 4 + 6 files changed, 191 insertions(+), 93 deletions(-) delete mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index abed6dc7b7a..e366eace280 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -457,53 +457,93 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - fun extractAnnotations(c: IrClass): Int { - var count = 0 - for (constructorCall: IrConstructorCall in c.annotations) { + private fun extractAnnotations(c: IrClass) { + for ((idx, constructorCall: IrConstructorCall) in c.annotations.withIndex()) { + extractAnnotation(constructorCall, useClassSource(c), idx) + } + } - // todo: do not extract JvmName, what else? + private fun extractAnnotation( + constructorCall: IrConstructorCall, + parent: Label, + idx: Int + ): Label { + val t = useType(constructorCall.type) - val t = useType(constructorCall.type) - val annotated = useClassSource(c) + val id = tw.getLabelFor("@\"annotation;{$parent};{${t.javaResult.id}}\"") + tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, t.kotlinResult.id) - val id = tw.getLabelFor("@\"annotation;{$annotated};{${t.javaResult.id}}\"") - tw.writeExprs_declannotation(id, t.javaResult.id, annotated, count++) - tw.writeExprsKotlinType(id, t.kotlinResult.id) + val locId = tw.getLocation(constructorCall) + tw.writeHasLocation(id, locId) - 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().firstOrNull { it.name == param.name } - if (prop == null) { - continue - } - - val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression - - when (v) { - is IrConst<*> -> { - val exprId = extractConstant(v, id, i) - if (exprId != null) { - - tw.writeAnnotValue(id, useFunction(prop.getter!!), exprId) - } - } - /* - Integer types; - Enum types; - String type; - Classes; - Other annotation types; - Arrays of any type listed above. - */ - - } + 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 exprId = extractAnnotationValueExpression(v, id, i) + if (exprId != null) { + tw.writeAnnotValue(id, useFunction(prop.getter!!), exprId) } } + return id + } - return count + private fun extractAnnotationValueExpression( + v: IrExpression?, + parent: Label, + idx: Int): Label? { + + return when (v) { + is IrConst<*> -> { + extractConstant(v, parent, idx) + } + is IrGetEnumValue -> { + extractEnumValue(v, parent, idx, null, null) + } + is IrClassReference -> { + extractClassReference(v, parent, idx, null, null) + } + is IrConstructorCall -> { + extractAnnotation(v, parent, idx) + } + is IrVararg -> { + val eId = tw.getFreshIdLabel() + val type = useType(v.type) + tw.writeExprs_arrayinit(eId, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(eId, type.kotlinResult.id) + tw.writeHasLocation(eId, 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, eId, index) + } } + + eId + } + // is IrErrorExpression + // null + else -> { + val eId = tw.getFreshIdLabel() + val type = useType(v?.type ?: pluginContext.irBuiltIns.unitType) + tw.writeExprs_errorexpr(eId, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(eId, type.kotlinResult.id) + + if (v != null) { + tw.writeHasLocation(eId, tw.getLocation(v)) + } + eId + } + } } fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label { @@ -2160,7 +2200,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) { @@ -2170,7 +2210,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) } @@ -3691,19 +3731,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) + val id = extractEnumValue(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrSetValue, is IrSetField -> { @@ -3947,14 +3975,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) @@ -4153,6 +4174,53 @@ open class KotlinFileExtractor( extractExpressionExpr(loop.condition, callable, id, 0, id) } + private fun extractClassReference( + e: IrClassReference, + parent: Label, + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label? + ): Label { + val id = tw.getFreshIdLabel() + val locId = tw.getLocation(e) + val type = useType(e.type) + tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + tw.writeHasLocation(id, locId) + + enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) } + enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) } + + extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt) + return id + } + + private fun extractEnumValue( + e: IrGetEnumValue, + parent: Label, + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label? + ): Label { + val id = tw.getFreshIdLabel() + 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) + tw.writeHasLocation(id, locId) + + enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) } + enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) } + + val owner = getBoundSymbolOwner(e.symbol, e) ?: return id + + val vId = useEnumEntry(owner) + tw.writeVariableBinding(id, vId) + + extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) + return id + } + // 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 @@ -5091,10 +5159,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 { + 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) + if (enclosingCallable != null) { + tw.writeCallableEnclosingExpr(id, enclosingCallable) + } + if (enclosingStmt != null) { + tw.writeStatementEnclosingExpr(id, enclosingStmt) + } return id } @@ -5136,7 +5208,7 @@ 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): 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) @@ -5154,8 +5226,8 @@ open class KotlinFileExtractor( typeArgs: List, location: Label, parentExpr: Label, - enclosingCallable: Label, - enclosingStmt: Label, + enclosingCallable: Label?, + enclosingStmt: Label?, startIndex: Int = 0, reverse: Boolean = false ) { 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/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected deleted file mode 100644 index 28e24b18b44..00000000000 --- a/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected +++ /dev/null @@ -1 +0,0 @@ -| file:///modules/java.base/java/util/Random.class:0:0:0:0 | RandomGeneratorProperties | Annotation | 1 | gap | 0, 2, 3, 4, 5 | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 2d34788a76e..57a8b571306 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -16,14 +16,18 @@ def.kt: #-----| 1: (Annotations) # 1| 2: [Method] y # 3| 3: [Interface] ReplaceWith +#-----| -3: (Annotations) # 3| 1: [Method] expression # 5| 4: [Interface] Deprecated +#-----| -3: (Annotations) # 6| 1: [Method] message # 7| 2: [Method] replaceWith # 9| 5: [Class] X #-----| -3: (Annotations) # 9| 1: [Annotation] Deprecated # 0| 1: [StringLiteral] This class is deprecated +# 0| 1: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] Y # 10| 2: [Annotation] SomeAnnotation # 0| 1: [IntegerLiteral] 5 # 0| 1: [StringLiteral] a @@ -33,29 +37,36 @@ def.kt: # 11| 1: [BlockStmt] { ... } use.java: # 0| [CompilationUnit] use -# 2| 1: [Class] use +# 6| 1: [Class] use +#-----| -3: (Annotations) +# 2| 1: [Annotation] Deprecated +# 3| 1: [StringLiteral] "This class is deprecated" +# 4| 2: [Annotation] ReplaceWith +# 4| 1: [StringLiteral] "Y" +# 5| 2: [Annotation] SomeAnnotation +# 5| 2: [StringLiteral] "b" #-----| -1: (Base Types) -# 2| 0: [TypeAccess] SomeAnnotation -# 4| 2: [Method] abc +# 6| 0: [TypeAccess] SomeAnnotation +# 8| 2: [Method] abc #-----| 1: (Annotations) -# 3| 1: [Annotation] Override -# 4| 3: [TypeAccess] int -# 4| 5: [BlockStmt] { ... } -# 4| 0: [ReturnStmt] return ... -# 4| 0: [IntegerLiteral] 1 -# 6| 3: [Method] y +# 7| 1: [Annotation] Override +# 8| 3: [TypeAccess] int +# 8| 5: [BlockStmt] { ... } +# 8| 0: [ReturnStmt] return ... +# 8| 0: [IntegerLiteral] 1 +# 10| 3: [Method] y #-----| 1: (Annotations) -# 5| 1: [Annotation] Override -# 6| 3: [TypeAccess] String -# 6| 5: [BlockStmt] { ... } -# 6| 0: [ReturnStmt] return ... -# 6| 0: [StringLiteral] "" -# 9| 4: [Method] annotationType -#-----| 1: (Annotations) -# 8| 1: [Annotation] Override -# 9| 3: [TypeAccess] Class -# 9| 0: [WildcardTypeAccess] ? ... -# 9| 0: [TypeAccess] Annotation -# 9| 5: [BlockStmt] { ... } +# 9| 1: [Annotation] Override +# 10| 3: [TypeAccess] String +# 10| 5: [BlockStmt] { ... } # 10| 0: [ReturnStmt] return ... -# 10| 0: [NullLiteral] null +# 10| 0: [StringLiteral] "" +# 13| 4: [Method] annotationType +#-----| 1: (Annotations) +# 12| 1: [Annotation] Override +# 13| 3: [TypeAccess] Class +# 13| 0: [WildcardTypeAccess] ? ... +# 13| 0: [TypeAccess] Annotation +# 13| 5: [BlockStmt] { ... } +# 14| 0: [ReturnStmt] return ... +# 14| 0: [NullLiteral] null 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 824dd2d6d21..c131b3ed5bc 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -5,16 +5,26 @@ annotationDeclarations | def.kt:5:1:7:51 | Deprecated | def.kt:6:5:6:23 | message | | def.kt:5:1:7:51 | Deprecated | def.kt:7:5:7:50 | replaceWith | annotations +| def.kt:0:0:0:0 | ReplaceWith | def.kt:9:1:9:57 | Deprecated | def.kt:3:1:3:52 | ReplaceWith | | def.kt:9:1:9:57 | Deprecated | def.kt:9:1:11:7 | X | def.kt:5:1:7:51 | Deprecated | | def.kt:10:1:10:24 | SomeAnnotation | def.kt:9:1:11:7 | X | def.kt:1:1:1:87 | SomeAnnotation | +| use.java:2:1:4:48 | Deprecated | use.java:6:14:6:16 | use | def.kt:5:1:7:51 | Deprecated | +| use.java:4:18:4:47 | ReplaceWith | use.java:2:1:4:48 | Deprecated | def.kt:3:1:3:52 | ReplaceWith | +| use.java:5:1:5:24 | SomeAnnotation | use.java:6:14:6:16 | use | def.kt:1:1:1:87 | SomeAnnotation | annotationValues +| def.kt:0:0:0:0 | ReplaceWith | def.kt:0:0:0:0 | Y | +| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | ReplaceWith | | def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | This class is deprecated | | def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | 5 | | def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | a | +| use.java:2:1:4:48 | Deprecated | use.java:3:14:3:39 | "This class is deprecated" | +| use.java:2:1:4:48 | Deprecated | use.java:4:18:4:47 | ReplaceWith | +| use.java:4:18:4:47 | ReplaceWith | use.java:4:44:4:46 | "Y" | +| use.java:5:1:5:24 | SomeAnnotation | use.java:5:21:5:23 | "b" | #select | def.kt:0:0:0:0 | DefKt | Class | | def.kt:1:1:1:87 | SomeAnnotation | Interface | | def.kt:3:1:3:52 | ReplaceWith | Interface | | def.kt:5:1:7:51 | Deprecated | Interface | | def.kt:9:1:11:7 | X | Class | -| use.java:2:14:2:16 | use | Class | +| use.java:6:14:6:16 | use | Class | 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 9b9191b849f..56307b9180b 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/use.java +++ b/java/ql/test/kotlin/library-tests/annotation_classes/use.java @@ -1,4 +1,8 @@ +@Deprecated( + message = "This class is deprecated", + replaceWith = @ReplaceWith(expression = "Y")) +@SomeAnnotation(y = "b") public class use implements SomeAnnotation { @Override public int abc() { return 1; } From b5ae43a8872cb2dba733cf8507bb2eb35d4bf6af Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 12 Apr 2022 16:04:29 +0200 Subject: [PATCH 064/136] Remove empty annotations node from PrintAST --- java/ql/lib/semmle/code/java/PrintAst.qll | 7 ++++++- .../library-tests/annotation_classes/PrintAst.expected | 4 ---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index d6420f2e4ca..3093c9b2643 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 diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 57a8b571306..36ab7c99887 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -11,15 +11,11 @@ def.kt: # 14| 0: [MethodAccess] abc(...) # 14| -1: [VarAccess] a # 1| 2: [Interface] SomeAnnotation -#-----| -3: (Annotations) # 1| 1: [Method] abc -#-----| 1: (Annotations) # 1| 2: [Method] y # 3| 3: [Interface] ReplaceWith -#-----| -3: (Annotations) # 3| 1: [Method] expression # 5| 4: [Interface] Deprecated -#-----| -3: (Annotations) # 6| 1: [Method] message # 7| 2: [Method] replaceWith # 9| 5: [Class] X From 1898f94472c1a46c34d29e307555bf609261125e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 12 Apr 2022 16:44:44 +0200 Subject: [PATCH 065/136] Filter expressions to source files in tests --- java/ql/test/kotlin/library-tests/exprs/exprs.ql | 1 + java/ql/test/kotlin/library-tests/literals/literals.ql | 1 + java/ql/test/kotlin/library-tests/stmts/exprs.ql | 1 + java/ql/test/kotlin/library-tests/variables/variableAccesses.ql | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) 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/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/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() } From b73bfd61339466da9e0971700ef4093c52888248 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 12 Apr 2022 16:53:00 +0200 Subject: [PATCH 066/136] Compilation fixup --- .../src/main/kotlin/KotlinFileExtractor.kt | 180 +++++++++--------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index e366eace280..1b3abd847d9 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -498,7 +498,7 @@ open class KotlinFileExtractor( return when (v) { is IrConst<*> -> { - extractConstant(v, parent, idx) + extractConstant(v, parent, idx, null, null) } is IrGetEnumValue -> { extractEnumValue(v, parent, idx, null, null) @@ -558,7 +558,7 @@ open class KotlinFileExtractor( val interfaceId = id.cast() tw.writeInterfaces(interfaceId, cls, pkgId, interfaceId) - if (kind == ClassKind.ANNOTATION_CLASS) { + if (c.kind == ClassKind.ANNOTATION_CLASS) { tw.writeIsAnnotType(interfaceId) } } else { @@ -586,12 +586,12 @@ open class KotlinFileExtractor( c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx, javaClass?.typeParameters?.getOrNull(idx)) } if (extractDeclarations) { - if (kind == ClassKind.ANNOTATION_CLASS) { + if (c.kind == ClassKind.ANNOTATION_CLASS) { c.declarations .filterIsInstance() .map { val getter = it.getter!! - val label = extractFunction(getter, id, false, null, listOf()) + val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, null, listOf()) tw.writeIsAnnotElem(label!!.cast()) } } else { @@ -3491,10 +3491,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) = @@ -3513,7 +3513,7 @@ open class KotlinFileExtractor( extractExprContext(it, locId, callable, enclosingStmt) } - private fun extractConstantInteger(v: Number, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + private fun extractConstantInteger(v: Number, locId: Label, parent: Label, idx: Int, callable: Label?, enclosingStmt: Label?) = tw.getFreshIdLabel().also { val type = useType(pluginContext.irBuiltIns.intType) tw.writeExprs_integerliteral(it, type.javaResult.id, parent, idx) @@ -3522,7 +3522,7 @@ open class KotlinFileExtractor( extractExprContext(it, locId, callable, enclosingStmt) } - private fun extractNull(t: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + private fun extractNull(t: IrType, locId: Label, parent: Label, idx: Int, callable: Label?, enclosingStmt: Label?) = tw.getFreshIdLabel().also { val type = useType(t) tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx) @@ -3698,11 +3698,7 @@ open class KotlinFileExtractor( } is IrConst<*> -> { val exprParent = parent.expr(e, callable) - val id = extractConstant(e, exprParent.parent, exprParent.idx) - if (id != null) { - tw.writeCallableEnclosingExpr(id, callable) - tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt) - } + extractConstant(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrGetValue -> { val exprParent = parent.expr(e, callable) @@ -3731,7 +3727,7 @@ open class KotlinFileExtractor( } is IrGetEnumValue -> { val exprParent = parent.expr(e, callable) - val id = extractEnumValue(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) + extractEnumValue(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) } is IrSetValue, is IrSetField -> { @@ -4180,20 +4176,16 @@ open class KotlinFileExtractor( idx: Int, enclosingCallable: Label?, enclosingStmt: Label? - ): Label { - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(e) - val type = useType(e.type) - tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - tw.writeHasLocation(id, locId) + ) = + tw.getFreshIdLabel().also { id -> + val locId = tw.getLocation(e) + val type = useType(e.type) + tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + extractExprContext(id, locId, enclosingCallable, enclosingStmt) - enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) } - enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) } - - extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt) - return id - } + extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt) + } private fun extractEnumValue( e: IrGetEnumValue, @@ -4201,25 +4193,23 @@ open class KotlinFileExtractor( idx: Int, enclosingCallable: Label?, enclosingStmt: Label? - ): Label { - val id = tw.getFreshIdLabel() - 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) - tw.writeHasLocation(id, locId) + ) = + tw.getFreshIdLabel().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) - enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) } - enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) } + getBoundSymbolOwner(e.symbol, e)?.let { owner -> - val owner = getBoundSymbolOwner(e.symbol, e) ?: return id + val vId = useEnumEntry(owner) + tw.writeVariableBinding(id, vId) - val vId = useEnumEntry(owner) - tw.writeVariableBinding(id, vId) + extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) - extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) - return id - } + } + } // 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 @@ -4231,72 +4221,82 @@ open class KotlinFileExtractor( private fun extractConstant( e: IrConst<*>, parent: Label, - idx: Int + idx: Int, + enclosingCallable: Label?, + enclosingStmt: Label? ): Label? { val v = e.value - when { + return 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) + extractConstantInteger(v, tw.getLocation(e), parent, idx, enclosingCallable, 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) + tw.getFreshIdLabel().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 -> { - 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) + tw.getFreshIdLabel().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 -> { - 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) + tw.getFreshIdLabel().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 -> { - 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) + tw.getFreshIdLabel().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 -> { - 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) + tw.getFreshIdLabel().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 -> { - 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) + tw.getFreshIdLabel().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), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) + extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt) } else -> { - logger.errorElement("Unrecognised IrConst: " + v.javaClass, e) + null.also { + logger.errorElement("Unrecognised IrConst: " + v.javaClass, e) + } } } } From a0cd9fea3439523266183ad8c07965d01c62a766 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 13 Apr 2022 08:48:17 +0200 Subject: [PATCH 067/136] Fix more not from source expressions in tests --- java/ql/test/kotlin/library-tests/methods/exprs.ql | 1 + 1 file changed, 1 insertion(+) 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() From f465dd536218fb60cd30746c3dbb53fef68996ee Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 13 Apr 2022 09:58:45 +0200 Subject: [PATCH 068/136] Add more annotation tests --- .../annotation_classes/Annot0j.java | 3 + .../annotation_classes/Annot1j.java | 15 ++ .../annotation_classes/PrintAst.expected | 165 ++++++++++++------ .../annotation_classes/classes.expected | 70 +++++--- .../library-tests/annotation_classes/def.kt | 32 ++-- .../library-tests/annotation_classes/use.java | 15 +- 6 files changed, 197 insertions(+), 103 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/Annot0j.java create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/Annot1j.java 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 index 36ab7c99887..221082cafd9 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -1,68 +1,117 @@ +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 -# 13| 1: [Method] fn +# 23| 1: [Method] fn #-----| 4: (Parameters) -# 13| 0: [Parameter] a -# 13| 5: [BlockStmt] { ... } -# 14| 0: [ExprStmt] ; -# 14| 0: [MethodAccess] println(...) -# 14| -1: [TypeAccess] ConsoleKt -# 14| 0: [MethodAccess] abc(...) -# 14| -1: [VarAccess] a -# 1| 2: [Interface] SomeAnnotation -# 1| 1: [Method] abc -# 1| 2: [Method] y -# 3| 3: [Interface] ReplaceWith -# 3| 1: [Method] expression -# 5| 4: [Interface] Deprecated -# 6| 1: [Method] message -# 7| 2: [Method] replaceWith -# 9| 5: [Class] X +# 23| 0: [Parameter] a +# 23| 5: [BlockStmt] { ... } +# 24| 0: [ExprStmt] ; +# 24| 0: [MethodAccess] println(...) +# 24| -1: [TypeAccess] ConsoleKt +# 24| 0: [MethodAccess] a(...) +# 24| -1: [VarAccess] a +# 3| 2: [Interface] Annot0k +# 3| 1: [Method] a +# 5| 3: [Interface] Annot1k +# 6| 1: [Method] a +# 7| 2: [Method] b +# 8| 3: [Method] c +# 9| 4: [Method] d +# 10| 5: [Method] e +# 11| 6: [Method] f +# 14| 4: [Class] X +# 14| 1: [Constructor] X +# 14| 5: [BlockStmt] { ... } +# 14| 0: [SuperConstructorInvocationStmt] super(...) +# 14| 1: [BlockStmt] { ... } +# 15| 5: [Class] Y +# 0| 2: [Method] values +# 0| 2: [Method] valueOf +#-----| 4: (Parameters) +# 0| 0: [Parameter] value +# 15| 4: [Constructor] Y +# 15| 5: [BlockStmt] { ... } +# 15| 0: [ExprStmt] ; +# 15| 0: [ClassInstanceExpr] new Enum(...) +# 15| -3: [TypeAccess] Unit +# 15| 0: [TypeAccess] Y +# 15| 1: [BlockStmt] { ... } +# 19| 6: [Class] Z #-----| -3: (Annotations) -# 9| 1: [Annotation] Deprecated -# 0| 1: [StringLiteral] This class is deprecated -# 0| 1: [Annotation] ReplaceWith -# 0| 1: [StringLiteral] Y -# 10| 2: [Annotation] SomeAnnotation -# 0| 1: [IntegerLiteral] 5 -# 0| 1: [StringLiteral] a -# 11| 1: [Constructor] X -# 9| 5: [BlockStmt] { ... } -# 9| 0: [SuperConstructorInvocationStmt] super(...) -# 11| 1: [BlockStmt] { ... } +# 19| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 20| 2: [Annotation] Annot1k +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [StringLiteral] ab +# 0| 1: [TypeLiteral] X.class +# 0| 0: [TypeAccess] X +# 0| 1: [VarAccess] B +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] C +# 0| 1: [VarAccess] A +# 0| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 21| 1: [Constructor] Z +# 19| 5: [BlockStmt] { ... } +# 19| 0: [SuperConstructorInvocationStmt] super(...) +# 21| 1: [BlockStmt] { ... } use.java: # 0| [CompilationUnit] use -# 6| 1: [Class] use -#-----| -3: (Annotations) -# 2| 1: [Annotation] Deprecated -# 3| 1: [StringLiteral] "This class is deprecated" -# 4| 2: [Annotation] ReplaceWith -# 4| 1: [StringLiteral] "Y" -# 5| 2: [Annotation] SomeAnnotation -# 5| 2: [StringLiteral] "b" +# 1| 1: [Class] use #-----| -1: (Base Types) -# 6| 0: [TypeAccess] SomeAnnotation -# 8| 2: [Method] abc +# 1| 0: [TypeAccess] Annot0k +# 3| 2: [Method] a #-----| 1: (Annotations) -# 7| 1: [Annotation] Override -# 8| 3: [TypeAccess] int -# 8| 5: [BlockStmt] { ... } -# 8| 0: [ReturnStmt] return ... -# 8| 0: [IntegerLiteral] 1 -# 10| 3: [Method] y +# 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) -# 9| 1: [Annotation] Override -# 10| 3: [TypeAccess] String -# 10| 5: [BlockStmt] { ... } -# 10| 0: [ReturnStmt] return ... -# 10| 0: [StringLiteral] "" -# 13| 4: [Method] annotationType -#-----| 1: (Annotations) -# 12| 1: [Annotation] Override -# 13| 3: [TypeAccess] Class -# 13| 0: [WildcardTypeAccess] ? ... -# 13| 0: [TypeAccess] Annotation -# 13| 5: [BlockStmt] { ... } -# 14| 0: [ReturnStmt] return ... -# 14| 0: [NullLiteral] null +# 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 +# 12| 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 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 c131b3ed5bc..1482615c42a 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -1,30 +1,50 @@ annotationDeclarations -| def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:53:1:66 | abc | -| def.kt:1:1:1:87 | SomeAnnotation | def.kt:1:69:1:86 | y | -| def.kt:3:1:3:52 | ReplaceWith | def.kt:3:30:3:51 | expression | -| def.kt:5:1:7:51 | Deprecated | def.kt:6:5:6:23 | message | -| def.kt:5:1:7:51 | Deprecated | def.kt:7:5:7:50 | replaceWith | +| 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:3:1:3:60 | Annot0k | def.kt:3:44:3:59 | a | +| def.kt:5:1:12:1 | Annot1k | def.kt:6:5:6:18 | a | +| def.kt:5:1:12:1 | Annot1k | def.kt:7:5:7:24 | b | +| def.kt:5:1:12:1 | Annot1k | def.kt:8:5:8:31 | c | +| def.kt:5:1:12:1 | Annot1k | def.kt:9:5:9:18 | d | +| def.kt:5:1:12:1 | Annot1k | def.kt:10:5:10:32 | e | +| def.kt:5:1:12:1 | Annot1k | def.kt:11:5:11:31 | f | annotations -| def.kt:0:0:0:0 | ReplaceWith | def.kt:9:1:9:57 | Deprecated | def.kt:3:1:3:52 | ReplaceWith | -| def.kt:9:1:9:57 | Deprecated | def.kt:9:1:11:7 | X | def.kt:5:1:7:51 | Deprecated | -| def.kt:10:1:10:24 | SomeAnnotation | def.kt:9:1:11:7 | X | def.kt:1:1:1:87 | SomeAnnotation | -| use.java:2:1:4:48 | Deprecated | use.java:6:14:6:16 | use | def.kt:5:1:7:51 | Deprecated | -| use.java:4:18:4:47 | ReplaceWith | use.java:2:1:4:48 | Deprecated | def.kt:3:1:3:52 | ReplaceWith | -| use.java:5:1:5:24 | SomeAnnotation | use.java:6:14:6:16 | use | def.kt:1:1:1:87 | SomeAnnotation | +| def.kt:0:0:0:0 | Annot0k | def.kt:20:1:20:40 | Annot1k | def.kt:3:1:3:60 | Annot0k | +| def.kt:19:1:19:17 | Annot0k | def.kt:19:1:21:10 | Z | def.kt:3:1:3:60 | Annot0k | +| def.kt:20:1:20:40 | Annot1k | def.kt:19:1:21:10 | Z | def.kt:5:1:12:1 | Annot1k | +| use.java:10:5:10:21 | Annot0j | use.java:12:18:12:18 | Z | Annot0j.java:1:19:1:25 | Annot0j | +| use.java:11:5:11:90 | Annot1j | use.java:12:18:12: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 | annotationValues -| def.kt:0:0:0:0 | ReplaceWith | def.kt:0:0:0:0 | Y | -| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | ReplaceWith | -| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | This class is deprecated | -| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | 5 | -| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | a | -| use.java:2:1:4:48 | Deprecated | use.java:3:14:3:39 | "This class is deprecated" | -| use.java:2:1:4:48 | Deprecated | use.java:4:18:4:47 | ReplaceWith | -| use.java:4:18:4:47 | ReplaceWith | use.java:4:44:4:46 | "Y" | -| use.java:5:1:5:24 | SomeAnnotation | use.java:5:21:5:23 | "b" | +| def.kt:0:0:0:0 | Annot0k | def.kt:0:0:0:0 | 1 | +| def.kt:19:1:19:17 | Annot0k | def.kt:0:0:0:0 | 1 | +| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | 2 | +| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | Annot0k | +| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | B | +| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | X.class | +| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | ab | +| def.kt:20:1:20:40 | Annot1k | def.kt: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 | #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:1:1:1:87 | SomeAnnotation | Interface | -| def.kt:3:1:3:52 | ReplaceWith | Interface | -| def.kt:5:1:7:51 | Deprecated | Interface | -| def.kt:9:1:11:7 | X | Class | -| use.java:6:14:6:16 | use | Class | +| def.kt:3:1:3:60 | Annot0k | Interface | +| def.kt:5:1:12:1 | Annot1k | Interface | +| def.kt:14:1:14:10 | X | Class | +| def.kt:15:1:17:1 | Y | Class | +| def.kt:19:1:21:10 | Z | Class | +| use.java:1:14:1:16 | use | Class | +| use.java:12:18:12:18 | Z | Class | 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 132fceb4244..47e8c3ae755 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt +++ b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt @@ -1,16 +1,26 @@ -annotation class SomeAnnotation(@get:JvmName("abc") val x: Int = 5, val y: String = "") +import kotlin.reflect.KClass -annotation class ReplaceWith(val expression: String) +annotation class Annot0k(@get:JvmName("a") val abc: Int = 0) -annotation class Deprecated( - val message: String, - val replaceWith: ReplaceWith = ReplaceWith("")) +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) +) -@Deprecated("This class is deprecated", ReplaceWith("Y")) -@SomeAnnotation(y = "a") -class X - -fun fn(a: SomeAnnotation) { - println(a.x) +class X {} +enum class Y { + A,B,C +} + +@Annot0k(abc = 1) +@Annot1k(d = Y.B, e = arrayOf(Y.C, Y.A)) +class Z {} + +fun fn(a: Annot0k) { + println(a.abc) } 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 56307b9180b..60d0c9162c4 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/use.java +++ b/java/ql/test/kotlin/library-tests/annotation_classes/use.java @@ -1,16 +1,13 @@ - -@Deprecated( - message = "This class is deprecated", - replaceWith = @ReplaceWith(expression = "Y")) -@SomeAnnotation(y = "b") -public class use implements SomeAnnotation { +public class use implements Annot0k { @Override - public int abc() { return 1; } - @Override - public String y() { return ""; } + public int a() { return 1; } @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)) + public class Z { } } From 3e1d4a7400efd63e616984480cb7b68be591f9df Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 13 Apr 2022 09:59:26 +0200 Subject: [PATCH 069/136] Add more annotation tests, add `KClass` to `Class` substitution --- .../src/main/kotlin/utils/ClassNames.kt | 9 +++- .../annotation_classes/PrintAst.expected | 49 ++++++++++++++----- .../annotation_classes/classes.expected | 32 +++++++++--- .../library-tests/annotation_classes/def.kt | 2 + .../library-tests/annotation_classes/use.java | 2 + 5 files changed, 76 insertions(+), 18 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt index ab4010242a7..ccb649e9561 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource +import org.jetbrains.kotlin.name.ClassId // Adapted from Kotlin's interpreter/Utils.kt function 'internalName' // Translates class names into their JLS section 13.1 binary name, @@ -119,4 +120,10 @@ fun getContainingClassOrSelf(decl: IrDeclaration): IrClass? { } fun getJavaEquivalentClassId(c: IrClass) = - c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) } + c.fqNameWhenAvailable?.toUnsafe()?.let { + if (it.asString() == "kotlin.reflect.KClass") { + ClassId.fromString("java.lang.Class") + } else { + JavaToKotlinClassMap.mapKotlinToJava(it) + } + } diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 221082cafd9..bd8bced3744 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -22,15 +22,15 @@ Annot1j.java: def.kt: # 0| [CompilationUnit] def # 0| 1: [Class] DefKt -# 23| 1: [Method] fn +# 25| 1: [Method] fn #-----| 4: (Parameters) -# 23| 0: [Parameter] a -# 23| 5: [BlockStmt] { ... } -# 24| 0: [ExprStmt] ; -# 24| 0: [MethodAccess] println(...) -# 24| -1: [TypeAccess] ConsoleKt -# 24| 0: [MethodAccess] a(...) -# 24| -1: [VarAccess] a +# 25| 0: [Parameter] a +# 25| 5: [BlockStmt] { ... } +# 26| 0: [ExprStmt] ; +# 26| 0: [MethodAccess] println(...) +# 26| -1: [TypeAccess] ConsoleKt +# 26| 0: [MethodAccess] a(...) +# 26| -1: [VarAccess] a # 3| 2: [Interface] Annot0k # 3| 1: [Method] a # 5| 3: [Interface] Annot1k @@ -72,10 +72,21 @@ def.kt: # 0| 1: [VarAccess] A # 0| 1: [Annotation] Annot0k # 0| 1: [IntegerLiteral] 1 -# 21| 1: [Constructor] Z +# 21| 3: [Annotation] Annot0j +# 0| 1: [IntegerLiteral] 1 +# 22| 4: [Annotation] Annot1j +# 0| 1: [ErrorExpr] +# 0| 1: [ErrorExpr] +# 0| 1: [ErrorExpr] +# 0| 1: [VarAccess] B +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] C +# 0| 1: [VarAccess] A +# 0| 1: [ErrorExpr] +# 23| 1: [Constructor] Z # 19| 5: [BlockStmt] { ... } # 19| 0: [SuperConstructorInvocationStmt] super(...) -# 21| 1: [BlockStmt] { ... } +# 23| 1: [BlockStmt] { ... } use.java: # 0| [CompilationUnit] use # 1| 1: [Class] use @@ -97,7 +108,7 @@ use.java: # 6| 5: [BlockStmt] { ... } # 7| 0: [ReturnStmt] return ... # 7| 0: [NullLiteral] null -# 12| 4: [Class] Z +# 14| 4: [Class] Z #-----| -3: (Annotations) # 10| 1: [Annotation] Annot0j # 10| 1: [IntegerLiteral] 1 @@ -115,3 +126,19 @@ use.java: # 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/classes.expected b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected index 1482615c42a..9928a6f1243 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -15,11 +15,16 @@ annotationDeclarations | def.kt:5:1:12:1 | Annot1k | def.kt:11:5:11:31 | f | annotations | def.kt:0:0:0:0 | Annot0k | def.kt:20:1:20:40 | Annot1k | def.kt:3:1:3:60 | Annot0k | -| def.kt:19:1:19:17 | Annot0k | def.kt:19:1:21:10 | Z | def.kt:3:1:3:60 | Annot0k | -| def.kt:20:1:20:40 | Annot1k | def.kt:19:1:21:10 | Z | def.kt:5:1:12:1 | Annot1k | -| use.java:10:5:10:21 | Annot0j | use.java:12:18:12:18 | Z | Annot0j.java:1:19:1:25 | Annot0j | -| use.java:11:5:11:90 | Annot1j | use.java:12:18:12:18 | Z | Annot1j.java:1:19:1:25 | Annot1j | +| def.kt:19:1:19:17 | Annot0k | def.kt:19:1:23:10 | Z | def.kt:3:1:3:60 | Annot0k | +| def.kt:20:1:20:40 | Annot1k | def.kt:19:1:23:10 | Z | def.kt:5:1:12:1 | Annot1k | +| def.kt:21:1:21:17 | Annot0j | def.kt:19:1:23:10 | Z | Annot0j.java:1:19:1:25 | Annot0j | +| def.kt:22:1:22:40 | Annot1j | def.kt:19:1:23:10 | Z | Annot1j.java:1:19:1:25 | Annot1j | +| 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:3:1:3:60 | Annot0k | +| use.java:13:5:13:88 | Annot1k | use.java:14:18:14:18 | Z | def.kt:5:1:12:1 | Annot1k | +| use.java:13:73:13:87 | Annot0k | use.java:13:5:13:88 | Annot1k | def.kt:3:1:3:60 | Annot0k | annotationValues | def.kt:0:0:0:0 | Annot0k | def.kt:0:0:0:0 | 1 | | def.kt:19:1:19:17 | Annot0k | def.kt:0:0:0:0 | 1 | @@ -29,6 +34,13 @@ annotationValues | def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | X.class | | def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | ab | | def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | {...} | +| def.kt:21:1:21:17 | Annot0j | def.kt:0:0:0:0 | 1 | +| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | +| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | +| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | +| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | +| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | B | +| def.kt:22:1:22:40 | Annot1j | def.kt: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" | @@ -37,6 +49,14 @@ annotationValues | 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 | @@ -45,6 +65,6 @@ annotationValues | def.kt:5:1:12:1 | Annot1k | Interface | | def.kt:14:1:14:10 | X | Class | | def.kt:15:1:17:1 | Y | Class | -| def.kt:19:1:21:10 | Z | Class | +| def.kt:19:1:23:10 | Z | Class | | use.java:1:14:1:16 | use | Class | -| use.java:12:18:12:18 | Z | Class | +| use.java:14:18:14:18 | Z | Class | 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 47e8c3ae755..6398e3962d1 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt +++ b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt @@ -18,6 +18,8 @@ enum class Y { @Annot0k(abc = 1) @Annot1k(d = Y.B, e = arrayOf(Y.C, Y.A)) +@Annot0j(abc = 1) +@Annot1j(d = Y.B, e = arrayOf(Y.C, Y.A)) class Z {} fun fn(a: Annot0k) { 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 60d0c9162c4..ec0dd0fa447 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/use.java +++ b/java/ql/test/kotlin/library-tests/annotation_classes/use.java @@ -9,5 +9,7 @@ public class use implements Annot0k { @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 { } } From 96a407c9c54f989689a5b605efed57d3f4bf7fef Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 13 Apr 2022 11:18:43 +0200 Subject: [PATCH 070/136] WIP: extract annotations for all declarations --- .../src/main/kotlin/KotlinFileExtractor.kt | 20 +- .../CONSISTENCY/children.expected | 2 + .../annotation_classes/DB-CHECK.expected | 36 + .../annotation_classes/PrintAst.expected | 733 ++++++++++++++---- .../annotation_classes/classes.expected | 79 +- .../library-tests/annotation_classes/def.kt | 46 +- 6 files changed, 736 insertions(+), 180 deletions(-) create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected create mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 1b3abd847d9..303561e64e0 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -238,6 +238,7 @@ open class KotlinFileExtractor( addModifiers(id, "out") } + extractAnnotations(tp, id) return id } } @@ -457,9 +458,9 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - private fun extractAnnotations(c: IrClass) { + private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { for ((idx, constructorCall: IrConstructorCall) in c.annotations.withIndex()) { - extractAnnotation(constructorCall, useClassSource(c), idx) + extractAnnotation(constructorCall, parent, idx) } } @@ -627,7 +628,7 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(c, id) - extractAnnotations(c) + extractAnnotations(c, id) if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) @@ -819,6 +820,7 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) + extractAnnotations(vp, id) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -1358,6 +1360,8 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) + extractAnnotations(f, id) + return id } } @@ -1374,7 +1378,9 @@ open class KotlinFileExtractor( 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) + return extractField(id, "${f.name.asString()}$fNameSuffix", extractType, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal, isDirectlyExposedCompanionObjectField(f)) } } } @@ -1467,6 +1473,8 @@ open class KotlinFileExtractor( extractVisibility(p, id, p.visibility) + // TODO: extract annotations + if (p.isLateinit) { addModifiers(id, "lateinit") } @@ -1510,6 +1518,8 @@ open class KotlinFileExtractor( ee.correspondingClass?.let { extractDeclaration(it, extractPrivateMembers, extractFunctionBodies) } + + extractAnnotations(ee, id) } } } @@ -1526,6 +1536,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 } } diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected new file mode 100644 index 00000000000..0ea0953c90a --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected @@ -0,0 +1,2 @@ +| def.kt:5:1:21:60 | Annot0k | Interface | 0 | duplicate | 0, 1, 2, 3 | +| def.kt:23:1:23:8 | Annot0k | Annotation | 0 | duplicate | 0 | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected b/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected new file mode 100644 index 00000000000..742cc876428 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected @@ -0,0 +1,36 @@ +[INVALID_KEY_SET] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {parent, idx} does not functionally determine all fields. +Here is a pair of tuples that agree on the key set but differ at index 0: +Tuple 1 in row 10: (103,66,102,88,0) +Tuple 2 in row 116: (521,66,520,88,0) + Relevant element: Tuple 1: id=103 + Full ID for 103: @"annotation;(88);(102)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;kotlin.annotation.Target"}" + Relevant element: Tuple 2: id=521 + Full ID for 521: @"annotation;(88);(520)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;java.lang.annotation.Retention"}" + Relevant element: Tuple 1: typeid=102 + Full ID for 102: @"class;kotlin.annotation.Target" + Relevant element: Tuple 2: typeid=520 + Full ID for 520: @"class;java.lang.annotation.Retention" + Relevant element: parent=88 + Full ID for 88: @"class;Annot0k" +[INVALID_KEY_SET] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {parent, idx} does not functionally determine all fields. +Here is a pair of tuples that agree on the key set but differ at index 0: +Tuple 1 in row 28: (172,17,17,170,0) +Tuple 2 in row 130: (558,17,17,170,0) + Relevant element: Tuple 2: id=558 + Full ID for 558: @"annotationExpr;(170);0". The ID may expand to @"annotationExpr;{@"annotation;{@"class;Annot1k"};{@"class;Annot0k"}"};0" + Relevant element: typeid=17 + Full ID for 17: @"type;int" + Relevant element: Tuple 1: parent=170 + Full ID for 170: @"annotation;(151);(88)". The ID may expand to @"annotation;{@"class;Annot1k"};{@"class;Annot0k"}" + Relevant element: Tuple 2: parent=170 + Full ID for 170: @"annotation;(151);(88)". The ID may expand to @"annotation;{@"class;Annot1k"};{@"class;Annot0k"}" +[INVALID_KEY] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {id} does not functionally determine all fields. +Here is a pair of tuples that agree on the key set but differ at index 4: +Tuple 1 in row 10: (103,66,102,88,0) +Tuple 2 in row 11: (103,66,102,88,3) + Relevant element: id=103 + Full ID for 103: @"annotation;(88);(102)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;kotlin.annotation.Target"}" + Relevant element: typeid=102 + Full ID for 102: @"class;kotlin.annotation.Target" + Relevant element: parent=88 + Full ID for 88: @"class;Annot0k" diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index bd8bced3744..ebfd0bcf81f 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -1,144 +1,605 @@ +Annot0j.java: +# 1| [Interface] Annot0j +#-----| 1 -> [Method] abc + +# 2| [Method] abc +#-----| 3 -> [TypeAccess] int + +# 2| [TypeAccess] int + +Annot1j.java: +# 1| [Interface] Annot1j +#-----| 1 -> [Method] a +#-----| 2 -> [Method] b +#-----| 3 -> [Method] c +#-----| 4 -> [Method] d +#-----| 5 -> [Method] e +#-----| 6 -> [Method] f + +# 2| [Method] a +#-----| 3 -> [TypeAccess] int + +# 2| [TypeAccess] int + +# 4| [Method] b +#-----| 3 -> [TypeAccess] String + +# 4| [TypeAccess] String + +# 6| [Method] c +#-----| 3 -> [TypeAccess] Class<> + +# 6| [TypeAccess] Class<> + +def.kt: +# 34| [Class] Y +#-----| 2 -> [Method] values +#-----| 2 -> [Method] valueOf +#-----| 4 -> [Constructor] Y + +Annot1j.java: +# 8| [Method] d +#-----| 3 -> [TypeAccess] Y + +# 8| [TypeAccess] Y + +# 10| [Method] e +#-----| 3 -> [ArrayTypeAccess] ...[] + +# 10| [ArrayTypeAccess] ...[] +#-----| 0 -> [TypeAccess] Y + +# 10| [TypeAccess] Y + +# 12| [Method] f +#-----| 3 -> [TypeAccess] Annot0j + +# 12| [TypeAccess] Annot0j + +def.kt: +# 5| [Interface] Annot0k +#-----| -3 -> (Annotations) +#-----| 1 -> [Method] a + +# 21| [Method] a +#-----| 1 -> (Annotations) + +# 21| [Annotation] JvmName +#-----| 1 -> [StringLiteral] a + +# 0| [StringLiteral] a + +# 5| [Annotation] Target +#-----| 1 -> [ArrayInit] {...} + +# 0| [ArrayInit] {...} +#-----| 1 -> [VarAccess] CLASS +#-----| 1 -> [VarAccess] ANNOTATION_CLASS +#-----| 1 -> [VarAccess] TYPE_PARAMETER +#-----| 1 -> [VarAccess] PROPERTY +#-----| 1 -> [VarAccess] FIELD +#-----| 1 -> [VarAccess] LOCAL_VARIABLE +#-----| 1 -> [VarAccess] VALUE_PARAMETER +#-----| 1 -> [VarAccess] CONSTRUCTOR +#-----| 1 -> [VarAccess] FUNCTION +#-----| 1 -> [VarAccess] PROPERTY_GETTER +#-----| 1 -> [VarAccess] PROPERTY_SETTER +#-----| 1 -> [VarAccess] TYPE +#-----| 1 -> [VarAccess] FILE +#-----| 1 -> [VarAccess] TYPEALIAS + +# 0| [VarAccess] CLASS + +# 0| [VarAccess] ANNOTATION_CLASS + +# 0| [VarAccess] TYPE_PARAMETER + +# 0| [VarAccess] PROPERTY + +# 0| [VarAccess] FIELD + +# 0| [VarAccess] LOCAL_VARIABLE + +# 0| [VarAccess] VALUE_PARAMETER + +# 0| [VarAccess] CONSTRUCTOR + +# 0| [VarAccess] FUNCTION + +# 0| [VarAccess] PROPERTY_GETTER + +# 0| [VarAccess] PROPERTY_SETTER + +# 0| [VarAccess] TYPE + +# 0| [VarAccess] FILE + +# 0| [VarAccess] TYPEALIAS + +# 23| [Interface] Annot1k +#-----| -3 -> (Annotations) +#-----| 1 -> [Method] a +#-----| 2 -> [Method] b +#-----| 3 -> [Method] c +#-----| 4 -> [Method] d +#-----| 5 -> [Method] e +#-----| 6 -> [Method] f + +# 25| [Method] a + +# 26| [Method] b + +# 27| [Method] c + +# 28| [Method] d + +# 29| [Method] e + +# 30| [Method] f + +# 23| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 33| [Class] X +#-----| 1 -> [Constructor] X + +# 33| [Constructor] X +#-----| 5 -> [BlockStmt] { ... } + +# 33| [BlockStmt] { ... } +#-----| 0 -> [SuperConstructorInvocationStmt] super(...) +#-----| 1 -> [BlockStmt] { ... } + +# 33| [SuperConstructorInvocationStmt] super(...) + +# 33| [BlockStmt] { ... } + +# 34| [Constructor] Y +#-----| 5 -> [BlockStmt] { ... } + +# 34| [BlockStmt] { ... } +#-----| 0 -> [ExprStmt] ; +#-----| 1 -> [BlockStmt] { ... } + +# 34| [ExprStmt] ; +#-----| 0 -> [ClassInstanceExpr] new Enum(...) + +# 34| [ClassInstanceExpr] new Enum(...) +#-----| -3 -> [TypeAccess] Unit + +# 34| [TypeAccess] Unit +#-----| 0 -> [TypeAccess] Y + +# 34| [TypeAccess] Y + +# 34| [BlockStmt] { ... } + +# 0| [Method] values + +# 0| [Method] valueOf +#-----| 4 -> (Parameters) + +# 0| [Parameter] value + +# 38| [Class] Z +#-----| -3 -> (Annotations) +#-----| 1 -> [Constructor] Z + +# 42| [Constructor] Z +#-----| 1 -> (Annotations) +#-----| 5 -> [BlockStmt] { ... } + +# 41| [BlockStmt] { ... } +#-----| 0 -> [SuperConstructorInvocationStmt] super(...) +#-----| 1 -> [BlockStmt] { ... } + +# 42| [SuperConstructorInvocationStmt] super(...) + +# 42| [BlockStmt] { ... } + +# 41| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 38| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 1 + +# 0| [IntegerLiteral] 1 + +# 39| [Annotation] Annot1k +#-----| 1 -> [IntegerLiteral] 2 +#-----| 1 -> [StringLiteral] ab +#-----| 1 -> [TypeLiteral] X.class +#-----| 1 -> [VarAccess] B +#-----| 1 -> [ArrayInit] {...} +#-----| 1 -> [Annotation] Annot0k + +# 0| [IntegerLiteral] 2 + +# 0| [StringLiteral] ab + +# 0| [TypeLiteral] X.class +#-----| 0 -> [TypeAccess] X + +# 0| [TypeAccess] X + +# 0| [VarAccess] B + +# 0| [ArrayInit] {...} +#-----| 1 -> [VarAccess] C +#-----| 1 -> [VarAccess] A + +# 0| [VarAccess] C + +# 0| [VarAccess] A + +# 0| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 1 + +# 0| [IntegerLiteral] 1 + +# 0| [Class] DefKt +#-----| 2 -> [Method] fn +#-----| 3 -> [FieldDeclaration] int p; +#-----| 4 -> [Method] getP +#-----| 4 -> [Method] setP +#-----| 6 -> [ExtensionMethod] myExtension + +# 46| [Method] fn +#-----| 1 -> (Annotations) +#-----| 2 -> (Generic Parameters) +#-----| 4 -> (Parameters) +#-----| 5 -> [BlockStmt] { ... } + +# 46| [TypeVariable] T +#-----| 0 -> [Annotation] Annot0k + +# 46| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 46| [Parameter] a +#-----| -1 -> (Annotations) + +# 46| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 46| [BlockStmt] { ... } +#-----| 0 -> [ExprStmt] ; +#-----| 1 -> [LocalVariableDeclStmt] var ...; + +# 47| [ExprStmt] ; +#-----| 0 -> [MethodAccess] println(...) + +# 47| [MethodAccess] println(...) +#-----| -1 -> [TypeAccess] ConsoleKt +#-----| 0 -> [MethodAccess] a(...) + +# 47| [TypeAccess] ConsoleKt + +# 47| [MethodAccess] a(...) +#-----| -1 -> [VarAccess] a + +# 47| [VarAccess] a + +# 49| [LocalVariableDeclStmt] var ...; +#-----| 1 -> [LocalVariableDeclExpr] x + +# 49| [LocalVariableDeclExpr] x +#-----| 0 -> [IntegerLiteral] 10 + +# 50| [IntegerLiteral] 10 + +# 45| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 57| [Method] getP +#-----| 1 -> (Annotations) +#-----| 5 -> [BlockStmt] { ... } + +# 57| [BlockStmt] { ... } +#-----| 0 -> [ReturnStmt] return ... + +# 57| [ReturnStmt] return ... +#-----| 0 -> [VarAccess] p + +# 57| [VarAccess] p + +# 54| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 57| [Method] setP +#-----| 1 -> (Annotations) +#-----| 4 -> (Parameters) +#-----| 5 -> [BlockStmt] { ... } + +# 57| [Parameter] + +# 57| [BlockStmt] { ... } +#-----| 0 -> [ExprStmt] ; + +# 57| [ExprStmt] ; +#-----| 0 -> [AssignExpr] ...=... + +# 57| [AssignExpr] ...=... +#-----| 0 -> [VarAccess] p +#-----| 1 -> [VarAccess] + +# 57| [VarAccess] p + +# 57| [VarAccess] + +# 55| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 56| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 53| [FieldDeclaration] int p; +#-----| -2 -> (Annotations) +#-----| -1 -> [TypeAccess] int +#-----| 0 -> [IntegerLiteral] 5 + +# 53| [TypeAccess] int + +# 59| [ExtensionMethod] myExtension +#-----| 4 -> (Parameters) +#-----| 5 -> [BlockStmt] { ... } + +# 59| [Parameter] +#-----| -1 -> (Annotations) + +# 59| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 0 + +# 0| [IntegerLiteral] 0 + +# 59| [BlockStmt] { ... } + +# 57| [IntegerLiteral] 5 + +use.java: +# 1| [Class] use +#-----| -1 -> (Base Types) +#-----| 2 -> [Method] a +#-----| 3 -> [Method] annotationType +#-----| 4 -> [Class] Z + +# 1| [TypeAccess] Annot0k + +# 3| [Method] a +#-----| 1 -> (Annotations) +#-----| 3 -> [TypeAccess] int +#-----| 5 -> [BlockStmt] { ... } + +# 2| [Annotation] Override + +# 3| [BlockStmt] { ... } +#-----| 0 -> [ReturnStmt] return ... + +# 3| [TypeAccess] int + +# 3| [ReturnStmt] return ... +#-----| 0 -> [IntegerLiteral] 1 + +# 3| [IntegerLiteral] 1 + +# 6| [Method] annotationType +#-----| 1 -> (Annotations) +#-----| 3 -> [TypeAccess] Class +#-----| 5 -> [BlockStmt] { ... } + +# 5| [Annotation] Override + +# 6| [BlockStmt] { ... } +#-----| 0 -> [ReturnStmt] return ... + +# 6| [TypeAccess] Class +#-----| 0 -> [WildcardTypeAccess] ? ... + +# 6| [WildcardTypeAccess] ? ... +#-----| 0 -> [TypeAccess] Annotation + +# 6| [TypeAccess] Annotation + +# 7| [ReturnStmt] return ... +#-----| 0 -> [NullLiteral] null + +# 7| [NullLiteral] null + +# 14| [Class] Z +#-----| -3 -> (Annotations) + +# 10| [Annotation] Annot0j +#-----| 1 -> [IntegerLiteral] 1 + +# 10| [IntegerLiteral] 1 + +# 12| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 1 + +# 12| [IntegerLiteral] 1 + +# 11| [Annotation] Annot1j +#-----| 1 -> [IntegerLiteral] 1 +#-----| 2 -> [StringLiteral] "ac" +#-----| 3 -> [TypeLiteral] X.class +#-----| 4 -> [VarAccess] Y.B +#-----| 5 -> [ArrayInit] {...} +#-----| 6 -> [Annotation] Annot0j + +# 11| [IntegerLiteral] 1 + +# 11| [StringLiteral] "ac" + +# 11| [TypeLiteral] X.class +#-----| 0 -> [TypeAccess] X + +# 11| [TypeAccess] X + +# 11| [VarAccess] Y.B +#-----| -1 -> [TypeAccess] Y + +# 11| [TypeAccess] Y + +# 11| [ArrayInit] {...} +#-----| 3 -> [VarAccess] Y.C +#-----| 4 -> [VarAccess] Y.A + +# 11| [VarAccess] Y.C +#-----| -1 -> [TypeAccess] Y + +# 11| [TypeAccess] Y + +# 11| [VarAccess] Y.A +#-----| -1 -> [TypeAccess] Y + +# 11| [TypeAccess] Y + +# 11| [Annotation] Annot0j +#-----| 1 -> [IntegerLiteral] 2 + +# 11| [IntegerLiteral] 2 + +# 13| [Annotation] Annot1k +#-----| 1 -> [IntegerLiteral] 1 +#-----| 2 -> [StringLiteral] "ac" +#-----| 3 -> [TypeLiteral] X.class +#-----| 4 -> [VarAccess] Y.B +#-----| 5 -> [ArrayInit] {...} +#-----| 6 -> [Annotation] Annot0k + +# 13| [IntegerLiteral] 1 + +# 13| [StringLiteral] "ac" + +# 13| [TypeLiteral] X.class +#-----| 0 -> [TypeAccess] X + +# 13| [TypeAccess] X + +# 13| [VarAccess] Y.B +#-----| -1 -> [TypeAccess] Y + +# 13| [TypeAccess] Y + +# 13| [ArrayInit] {...} +#-----| 3 -> [VarAccess] Y.C +#-----| 4 -> [VarAccess] Y.A + +# 13| [VarAccess] Y.C +#-----| -1 -> [TypeAccess] Y + +# 13| [TypeAccess] Y + +# 13| [VarAccess] Y.A +#-----| -1 -> [TypeAccess] Y + +# 13| [TypeAccess] Y + +# 13| [Annotation] Annot0k +#-----| 1 -> [IntegerLiteral] 2 + +# 13| [IntegerLiteral] 2 + +#-----| (Base Types) +#-----| 0 -> [TypeAccess] Annot0k + +#-----| (Annotations) +#-----| 4 -> [Annotation] Target + +#-----| (Annotations) +#-----| 1 -> [Annotation] JvmName + +#-----| (Annotations) +#-----| 3 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k +#-----| 2 -> [Annotation] Annot1k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0k + +#-----| (Annotations) +#-----| 1 -> [Annotation] Override + +#-----| (Annotations) +#-----| 1 -> [Annotation] Override + +#-----| (Annotations) +#-----| 1 -> [Annotation] Annot0j +#-----| 2 -> [Annotation] Annot1j +#-----| 3 -> [Annotation] Annot0k +#-----| 4 -> [Annotation] Annot1k + +#-----| (Parameters) +#-----| 0 -> [Parameter] value + +#-----| (Parameters) +#-----| 0 -> [Parameter] a + +#-----| (Parameters) +#-----| 0 -> [Parameter] + +#-----| (Parameters) +#-----| 0 -> [Parameter] + +#-----| (Generic Parameters) +#-----| 0 -> [TypeVariable] T + Annot0j.java: # 0| [CompilationUnit] Annot0j -# 1| 1: [Interface] Annot0j -# 2| 1: [Method] abc -# 2| 3: [TypeAccess] int +#-----| 1 -> [Interface] Annot0j + 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 +#-----| 1 -> [Interface] Annot1j + def.kt: # 0| [CompilationUnit] def -# 0| 1: [Class] DefKt -# 25| 1: [Method] fn -#-----| 4: (Parameters) -# 25| 0: [Parameter] a -# 25| 5: [BlockStmt] { ... } -# 26| 0: [ExprStmt] ; -# 26| 0: [MethodAccess] println(...) -# 26| -1: [TypeAccess] ConsoleKt -# 26| 0: [MethodAccess] a(...) -# 26| -1: [VarAccess] a -# 3| 2: [Interface] Annot0k -# 3| 1: [Method] a -# 5| 3: [Interface] Annot1k -# 6| 1: [Method] a -# 7| 2: [Method] b -# 8| 3: [Method] c -# 9| 4: [Method] d -# 10| 5: [Method] e -# 11| 6: [Method] f -# 14| 4: [Class] X -# 14| 1: [Constructor] X -# 14| 5: [BlockStmt] { ... } -# 14| 0: [SuperConstructorInvocationStmt] super(...) -# 14| 1: [BlockStmt] { ... } -# 15| 5: [Class] Y -# 0| 2: [Method] values -# 0| 2: [Method] valueOf -#-----| 4: (Parameters) -# 0| 0: [Parameter] value -# 15| 4: [Constructor] Y -# 15| 5: [BlockStmt] { ... } -# 15| 0: [ExprStmt] ; -# 15| 0: [ClassInstanceExpr] new Enum(...) -# 15| -3: [TypeAccess] Unit -# 15| 0: [TypeAccess] Y -# 15| 1: [BlockStmt] { ... } -# 19| 6: [Class] Z -#-----| -3: (Annotations) -# 19| 1: [Annotation] Annot0k -# 0| 1: [IntegerLiteral] 1 -# 20| 2: [Annotation] Annot1k -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [StringLiteral] ab -# 0| 1: [TypeLiteral] X.class -# 0| 0: [TypeAccess] X -# 0| 1: [VarAccess] B -# 0| 1: [ArrayInit] {...} -# 0| 1: [VarAccess] C -# 0| 1: [VarAccess] A -# 0| 1: [Annotation] Annot0k -# 0| 1: [IntegerLiteral] 1 -# 21| 3: [Annotation] Annot0j -# 0| 1: [IntegerLiteral] 1 -# 22| 4: [Annotation] Annot1j -# 0| 1: [ErrorExpr] -# 0| 1: [ErrorExpr] -# 0| 1: [ErrorExpr] -# 0| 1: [VarAccess] B -# 0| 1: [ArrayInit] {...} -# 0| 1: [VarAccess] C -# 0| 1: [VarAccess] A -# 0| 1: [ErrorExpr] -# 23| 1: [Constructor] Z -# 19| 5: [BlockStmt] { ... } -# 19| 0: [SuperConstructorInvocationStmt] super(...) -# 23| 1: [BlockStmt] { ... } +#-----| 1 -> [Class] DefKt +#-----| 2 -> [Interface] Annot0k +#-----| 3 -> [Interface] Annot1k +#-----| 4 -> [Class] X +#-----| 5 -> [Class] Y +#-----| 6 -> [Class] Z + 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 +#-----| 1 -> [Class] use 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 9928a6f1243..917bacb6337 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -6,41 +6,52 @@ annotationDeclarations | 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:3:1:3:60 | Annot0k | def.kt:3:44:3:59 | a | -| def.kt:5:1:12:1 | Annot1k | def.kt:6:5:6:18 | a | -| def.kt:5:1:12:1 | Annot1k | def.kt:7:5:7:24 | b | -| def.kt:5:1:12:1 | Annot1k | def.kt:8:5:8:31 | c | -| def.kt:5:1:12:1 | Annot1k | def.kt:9:5:9:18 | d | -| def.kt:5:1:12:1 | Annot1k | def.kt:10:5:10:32 | e | -| def.kt:5:1:12:1 | Annot1k | def.kt:11:5:11:31 | 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:20:1:20:40 | Annot1k | def.kt:3:1:3:60 | Annot0k | -| def.kt:19:1:19:17 | Annot0k | def.kt:19:1:23:10 | Z | def.kt:3:1:3:60 | Annot0k | -| def.kt:20:1:20:40 | Annot1k | def.kt:19:1:23:10 | Z | def.kt:5:1:12:1 | Annot1k | -| def.kt:21:1:21:17 | Annot0j | def.kt:19:1:23:10 | Z | Annot0j.java:1:19:1:25 | Annot0j | -| def.kt:22:1:22:40 | Annot1j | def.kt:19:1:23:10 | Z | Annot1j.java:1:19:1:25 | Annot1j | +| 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:6:46:13 | Annot0k | def.kt:46:6:46:15 | T | 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:3:1:3:60 | Annot0k | -| use.java:13:5:13:88 | Annot1k | use.java:14:18:14:18 | Z | def.kt:5:1:12:1 | Annot1k | -| use.java:13:73:13:87 | Annot0k | use.java:13:5:13:88 | Annot1k | def.kt:3:1:3:60 | Annot0k | +| 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:19:1:19:17 | Annot0k | def.kt:0:0:0:0 | 1 | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | 2 | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | Annot0k | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | B | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | X.class | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | ab | -| def.kt:20:1:20:40 | Annot1k | def.kt:0:0:0:0 | {...} | -| def.kt:21:1:21:17 | Annot0j | def.kt:0:0:0:0 | 1 | -| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | -| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | -| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | -| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | | -| def.kt:22:1:22:40 | Annot1j | def.kt:0:0:0:0 | B | -| def.kt:22:1:22:40 | Annot1j | 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 | Annot0k | +| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | B | +| 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 | ab | +| 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:6:46:13 | 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" | @@ -61,10 +72,10 @@ annotationValues | 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:3:1:3:60 | Annot0k | Interface | -| def.kt:5:1:12:1 | Annot1k | Interface | -| def.kt:14:1:14:10 | X | Class | -| def.kt:15:1:17:1 | Y | Class | -| def.kt:19:1:23:10 | Z | 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/def.kt b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt index 6398e3962d1..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,7 +1,26 @@ +@file:Annot0k + 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", @@ -18,11 +37,26 @@ enum class Y { @Annot0k(abc = 1) @Annot1k(d = Y.B, e = arrayOf(Y.C, Y.A)) -@Annot0j(abc = 1) -@Annot1j(d = Y.B, e = arrayOf(Y.C, Y.A)) -class Z {} - -fun fn(a: Annot0k) { - println(a.abc) +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 From fed770fcd1ca9de661ef2141228762e2564f6913 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 13 Apr 2022 11:48:46 +0200 Subject: [PATCH 071/136] Move kotlin annotations to negative child index --- .../src/main/kotlin/KotlinFileExtractor.kt | 4 +-- .../CONSISTENCY/children.expected | 2 -- .../annotation_classes/DB-CHECK.expected | 36 ------------------- .../annotation_classes/PrintAst.expected | 15 +++++--- .../annotation_classes/classes.expected | 1 + 5 files changed, 14 insertions(+), 44 deletions(-) delete mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected delete mode 100644 java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 303561e64e0..3c7b716bbcc 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -460,7 +460,7 @@ open class KotlinFileExtractor( private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { for ((idx, constructorCall: IrConstructorCall) in c.annotations.withIndex()) { - extractAnnotation(constructorCall, parent, idx) + extractAnnotation(constructorCall, parent, -1 - idx) } } @@ -471,7 +471,7 @@ open class KotlinFileExtractor( ): Label { val t = useType(constructorCall.type) - val id = tw.getLabelFor("@\"annotation;{$parent};{${t.javaResult.id}}\"") + val id = tw.getLabelFor("@\"annotation_kotlin;{$parent};{${t.javaResult.id}}\"") tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx) tw.writeExprsKotlinType(id, t.kotlinResult.id) diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected b/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected deleted file mode 100644 index 0ea0953c90a..00000000000 --- a/java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected +++ /dev/null @@ -1,2 +0,0 @@ -| def.kt:5:1:21:60 | Annot0k | Interface | 0 | duplicate | 0, 1, 2, 3 | -| def.kt:23:1:23:8 | Annot0k | Annotation | 0 | duplicate | 0 | diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected b/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected deleted file mode 100644 index 742cc876428..00000000000 --- a/java/ql/test/kotlin/library-tests/annotation_classes/DB-CHECK.expected +++ /dev/null @@ -1,36 +0,0 @@ -[INVALID_KEY_SET] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {parent, idx} does not functionally determine all fields. -Here is a pair of tuples that agree on the key set but differ at index 0: -Tuple 1 in row 10: (103,66,102,88,0) -Tuple 2 in row 116: (521,66,520,88,0) - Relevant element: Tuple 1: id=103 - Full ID for 103: @"annotation;(88);(102)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;kotlin.annotation.Target"}" - Relevant element: Tuple 2: id=521 - Full ID for 521: @"annotation;(88);(520)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;java.lang.annotation.Retention"}" - Relevant element: Tuple 1: typeid=102 - Full ID for 102: @"class;kotlin.annotation.Target" - Relevant element: Tuple 2: typeid=520 - Full ID for 520: @"class;java.lang.annotation.Retention" - Relevant element: parent=88 - Full ID for 88: @"class;Annot0k" -[INVALID_KEY_SET] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {parent, idx} does not functionally determine all fields. -Here is a pair of tuples that agree on the key set but differ at index 0: -Tuple 1 in row 28: (172,17,17,170,0) -Tuple 2 in row 130: (558,17,17,170,0) - Relevant element: Tuple 2: id=558 - Full ID for 558: @"annotationExpr;(170);0". The ID may expand to @"annotationExpr;{@"annotation;{@"class;Annot1k"};{@"class;Annot0k"}"};0" - Relevant element: typeid=17 - Full ID for 17: @"type;int" - Relevant element: Tuple 1: parent=170 - Full ID for 170: @"annotation;(151);(88)". The ID may expand to @"annotation;{@"class;Annot1k"};{@"class;Annot0k"}" - Relevant element: Tuple 2: parent=170 - Full ID for 170: @"annotation;(151);(88)". The ID may expand to @"annotation;{@"class;Annot1k"};{@"class;Annot0k"}" -[INVALID_KEY] predicate exprs(@expr id, int kind, @type typeid, @exprparent parent, int idx): The key set {id} does not functionally determine all fields. -Here is a pair of tuples that agree on the key set but differ at index 4: -Tuple 1 in row 10: (103,66,102,88,0) -Tuple 2 in row 11: (103,66,102,88,3) - Relevant element: id=103 - Full ID for 103: @"annotation;(88);(102)". The ID may expand to @"annotation;{@"class;Annot0k"};{@"class;kotlin.annotation.Target"}" - Relevant element: typeid=102 - Full ID for 102: @"class;kotlin.annotation.Target" - Relevant element: parent=88 - Full ID for 88: @"class;Annot0k" diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index ebfd0bcf81f..554a9837c28 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -63,6 +63,7 @@ def.kt: # 21| [Method] a #-----| 1 -> (Annotations) +#-----| 3 -> [Annotation] JvmName # 21| [Annotation] JvmName #-----| 1 -> [StringLiteral] a @@ -189,6 +190,7 @@ def.kt: # 42| [Constructor] Z #-----| 1 -> (Annotations) +#-----| 3 -> [Annotation] Annot0k #-----| 5 -> [BlockStmt] { ... } # 41| [BlockStmt] { ... } @@ -251,11 +253,12 @@ def.kt: # 46| [Method] fn #-----| 1 -> (Annotations) #-----| 2 -> (Generic Parameters) +#-----| 3 -> [Annotation] Annot0k #-----| 4 -> (Parameters) #-----| 5 -> [BlockStmt] { ... } # 46| [TypeVariable] T -#-----| 0 -> [Annotation] Annot0k +#-----| -1 -> [Annotation] Annot0k # 46| [Annotation] Annot0k #-----| 1 -> [IntegerLiteral] 0 @@ -264,6 +267,7 @@ def.kt: # 46| [Parameter] a #-----| -1 -> (Annotations) +#-----| 0 -> [Annotation] Annot0k # 46| [Annotation] Annot0k #-----| 1 -> [IntegerLiteral] 0 @@ -303,6 +307,7 @@ def.kt: # 57| [Method] getP #-----| 1 -> (Annotations) +#-----| 3 -> [Annotation] Annot0k #-----| 5 -> [BlockStmt] { ... } # 57| [BlockStmt] { ... } @@ -320,6 +325,7 @@ def.kt: # 57| [Method] setP #-----| 1 -> (Annotations) +#-----| 3 -> [Annotation] Annot0k #-----| 4 -> (Parameters) #-----| 5 -> [BlockStmt] { ... } @@ -362,6 +368,7 @@ def.kt: # 59| [Parameter] #-----| -1 -> (Annotations) +#-----| 0 -> [Annotation] Annot0k # 59| [Annotation] Annot0k #-----| 1 -> [IntegerLiteral] 0 @@ -520,13 +527,13 @@ use.java: #-----| 0 -> [TypeAccess] Annot0k #-----| (Annotations) -#-----| 4 -> [Annotation] Target +#-----| 5 -> [Annotation] Target #-----| (Annotations) -#-----| 1 -> [Annotation] JvmName +#-----| 2 -> [Annotation] JvmName #-----| (Annotations) -#-----| 3 -> [Annotation] Annot0k +#-----| 4 -> [Annotation] Annot0k #-----| (Annotations) #-----| 1 -> [Annotation] Annot0k 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 917bacb6337..6a60e04dd6f 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -14,6 +14,7 @@ annotationDeclarations | 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 +| annotation_classes.testproj/test.class.files/Annot1k.class:0:0:0:0 | Annot0k | def.kt:23:1:31:1 | Annot1k | def.kt:5:1:21:60 | Annot0k | | 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 | From df595c05f21d40a6378298681532aa58be6a122e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 14 Apr 2022 09:22:18 +0200 Subject: [PATCH 072/136] WIP: revert some annotation extraction to get proper tree in printast --- .../src/main/kotlin/KotlinFileExtractor.kt | 6 +- .../annotation_classes/PrintAst.expected | 776 ++++-------------- .../annotation_classes/classes.expected | 15 - 3 files changed, 175 insertions(+), 622 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 3c7b716bbcc..af8228856bc 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -238,7 +238,7 @@ open class KotlinFileExtractor( addModifiers(id, "out") } - extractAnnotations(tp, id) + //extractAnnotations(tp, id) return id } } @@ -820,7 +820,7 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) - extractAnnotations(vp, id) + //extractAnnotations(vp, id) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -1360,7 +1360,7 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) - extractAnnotations(f, id) + //extractAnnotations(f, id) return id } diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 554a9837c28..18c14a30a4f 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -1,612 +1,180 @@ -Annot0j.java: -# 1| [Interface] Annot0j -#-----| 1 -> [Method] abc - -# 2| [Method] abc -#-----| 3 -> [TypeAccess] int - -# 2| [TypeAccess] int - -Annot1j.java: -# 1| [Interface] Annot1j -#-----| 1 -> [Method] a -#-----| 2 -> [Method] b -#-----| 3 -> [Method] c -#-----| 4 -> [Method] d -#-----| 5 -> [Method] e -#-----| 6 -> [Method] f - -# 2| [Method] a -#-----| 3 -> [TypeAccess] int - -# 2| [TypeAccess] int - -# 4| [Method] b -#-----| 3 -> [TypeAccess] String - -# 4| [TypeAccess] String - -# 6| [Method] c -#-----| 3 -> [TypeAccess] Class<> - -# 6| [TypeAccess] Class<> - -def.kt: -# 34| [Class] Y -#-----| 2 -> [Method] values -#-----| 2 -> [Method] valueOf -#-----| 4 -> [Constructor] Y - -Annot1j.java: -# 8| [Method] d -#-----| 3 -> [TypeAccess] Y - -# 8| [TypeAccess] Y - -# 10| [Method] e -#-----| 3 -> [ArrayTypeAccess] ...[] - -# 10| [ArrayTypeAccess] ...[] -#-----| 0 -> [TypeAccess] Y - -# 10| [TypeAccess] Y - -# 12| [Method] f -#-----| 3 -> [TypeAccess] Annot0j - -# 12| [TypeAccess] Annot0j - -def.kt: -# 5| [Interface] Annot0k -#-----| -3 -> (Annotations) -#-----| 1 -> [Method] a - -# 21| [Method] a -#-----| 1 -> (Annotations) -#-----| 3 -> [Annotation] JvmName - -# 21| [Annotation] JvmName -#-----| 1 -> [StringLiteral] a - -# 0| [StringLiteral] a - -# 5| [Annotation] Target -#-----| 1 -> [ArrayInit] {...} - -# 0| [ArrayInit] {...} -#-----| 1 -> [VarAccess] CLASS -#-----| 1 -> [VarAccess] ANNOTATION_CLASS -#-----| 1 -> [VarAccess] TYPE_PARAMETER -#-----| 1 -> [VarAccess] PROPERTY -#-----| 1 -> [VarAccess] FIELD -#-----| 1 -> [VarAccess] LOCAL_VARIABLE -#-----| 1 -> [VarAccess] VALUE_PARAMETER -#-----| 1 -> [VarAccess] CONSTRUCTOR -#-----| 1 -> [VarAccess] FUNCTION -#-----| 1 -> [VarAccess] PROPERTY_GETTER -#-----| 1 -> [VarAccess] PROPERTY_SETTER -#-----| 1 -> [VarAccess] TYPE -#-----| 1 -> [VarAccess] FILE -#-----| 1 -> [VarAccess] TYPEALIAS - -# 0| [VarAccess] CLASS - -# 0| [VarAccess] ANNOTATION_CLASS - -# 0| [VarAccess] TYPE_PARAMETER - -# 0| [VarAccess] PROPERTY - -# 0| [VarAccess] FIELD - -# 0| [VarAccess] LOCAL_VARIABLE - -# 0| [VarAccess] VALUE_PARAMETER - -# 0| [VarAccess] CONSTRUCTOR - -# 0| [VarAccess] FUNCTION - -# 0| [VarAccess] PROPERTY_GETTER - -# 0| [VarAccess] PROPERTY_SETTER - -# 0| [VarAccess] TYPE - -# 0| [VarAccess] FILE - -# 0| [VarAccess] TYPEALIAS - -# 23| [Interface] Annot1k -#-----| -3 -> (Annotations) -#-----| 1 -> [Method] a -#-----| 2 -> [Method] b -#-----| 3 -> [Method] c -#-----| 4 -> [Method] d -#-----| 5 -> [Method] e -#-----| 6 -> [Method] f - -# 25| [Method] a - -# 26| [Method] b - -# 27| [Method] c - -# 28| [Method] d - -# 29| [Method] e - -# 30| [Method] f - -# 23| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 33| [Class] X -#-----| 1 -> [Constructor] X - -# 33| [Constructor] X -#-----| 5 -> [BlockStmt] { ... } - -# 33| [BlockStmt] { ... } -#-----| 0 -> [SuperConstructorInvocationStmt] super(...) -#-----| 1 -> [BlockStmt] { ... } - -# 33| [SuperConstructorInvocationStmt] super(...) - -# 33| [BlockStmt] { ... } - -# 34| [Constructor] Y -#-----| 5 -> [BlockStmt] { ... } - -# 34| [BlockStmt] { ... } -#-----| 0 -> [ExprStmt] ; -#-----| 1 -> [BlockStmt] { ... } - -# 34| [ExprStmt] ; -#-----| 0 -> [ClassInstanceExpr] new Enum(...) - -# 34| [ClassInstanceExpr] new Enum(...) -#-----| -3 -> [TypeAccess] Unit - -# 34| [TypeAccess] Unit -#-----| 0 -> [TypeAccess] Y - -# 34| [TypeAccess] Y - -# 34| [BlockStmt] { ... } - -# 0| [Method] values - -# 0| [Method] valueOf -#-----| 4 -> (Parameters) - -# 0| [Parameter] value - -# 38| [Class] Z -#-----| -3 -> (Annotations) -#-----| 1 -> [Constructor] Z - -# 42| [Constructor] Z -#-----| 1 -> (Annotations) -#-----| 3 -> [Annotation] Annot0k -#-----| 5 -> [BlockStmt] { ... } - -# 41| [BlockStmt] { ... } -#-----| 0 -> [SuperConstructorInvocationStmt] super(...) -#-----| 1 -> [BlockStmt] { ... } - -# 42| [SuperConstructorInvocationStmt] super(...) - -# 42| [BlockStmt] { ... } - -# 41| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 38| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 1 - -# 0| [IntegerLiteral] 1 - -# 39| [Annotation] Annot1k -#-----| 1 -> [IntegerLiteral] 2 -#-----| 1 -> [StringLiteral] ab -#-----| 1 -> [TypeLiteral] X.class -#-----| 1 -> [VarAccess] B -#-----| 1 -> [ArrayInit] {...} -#-----| 1 -> [Annotation] Annot0k - -# 0| [IntegerLiteral] 2 - -# 0| [StringLiteral] ab - -# 0| [TypeLiteral] X.class -#-----| 0 -> [TypeAccess] X - -# 0| [TypeAccess] X - -# 0| [VarAccess] B - -# 0| [ArrayInit] {...} -#-----| 1 -> [VarAccess] C -#-----| 1 -> [VarAccess] A - -# 0| [VarAccess] C - -# 0| [VarAccess] A - -# 0| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 1 - -# 0| [IntegerLiteral] 1 - -# 0| [Class] DefKt -#-----| 2 -> [Method] fn -#-----| 3 -> [FieldDeclaration] int p; -#-----| 4 -> [Method] getP -#-----| 4 -> [Method] setP -#-----| 6 -> [ExtensionMethod] myExtension - -# 46| [Method] fn -#-----| 1 -> (Annotations) -#-----| 2 -> (Generic Parameters) -#-----| 3 -> [Annotation] Annot0k -#-----| 4 -> (Parameters) -#-----| 5 -> [BlockStmt] { ... } - -# 46| [TypeVariable] T -#-----| -1 -> [Annotation] Annot0k - -# 46| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 46| [Parameter] a -#-----| -1 -> (Annotations) -#-----| 0 -> [Annotation] Annot0k - -# 46| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 46| [BlockStmt] { ... } -#-----| 0 -> [ExprStmt] ; -#-----| 1 -> [LocalVariableDeclStmt] var ...; - -# 47| [ExprStmt] ; -#-----| 0 -> [MethodAccess] println(...) - -# 47| [MethodAccess] println(...) -#-----| -1 -> [TypeAccess] ConsoleKt -#-----| 0 -> [MethodAccess] a(...) - -# 47| [TypeAccess] ConsoleKt - -# 47| [MethodAccess] a(...) -#-----| -1 -> [VarAccess] a - -# 47| [VarAccess] a - -# 49| [LocalVariableDeclStmt] var ...; -#-----| 1 -> [LocalVariableDeclExpr] x - -# 49| [LocalVariableDeclExpr] x -#-----| 0 -> [IntegerLiteral] 10 - -# 50| [IntegerLiteral] 10 - -# 45| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 57| [Method] getP -#-----| 1 -> (Annotations) -#-----| 3 -> [Annotation] Annot0k -#-----| 5 -> [BlockStmt] { ... } - -# 57| [BlockStmt] { ... } -#-----| 0 -> [ReturnStmt] return ... - -# 57| [ReturnStmt] return ... -#-----| 0 -> [VarAccess] p - -# 57| [VarAccess] p - -# 54| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 57| [Method] setP -#-----| 1 -> (Annotations) -#-----| 3 -> [Annotation] Annot0k -#-----| 4 -> (Parameters) -#-----| 5 -> [BlockStmt] { ... } - -# 57| [Parameter] - -# 57| [BlockStmt] { ... } -#-----| 0 -> [ExprStmt] ; - -# 57| [ExprStmt] ; -#-----| 0 -> [AssignExpr] ...=... - -# 57| [AssignExpr] ...=... -#-----| 0 -> [VarAccess] p -#-----| 1 -> [VarAccess] - -# 57| [VarAccess] p - -# 57| [VarAccess] - -# 55| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 56| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 53| [FieldDeclaration] int p; -#-----| -2 -> (Annotations) -#-----| -1 -> [TypeAccess] int -#-----| 0 -> [IntegerLiteral] 5 - -# 53| [TypeAccess] int - -# 59| [ExtensionMethod] myExtension -#-----| 4 -> (Parameters) -#-----| 5 -> [BlockStmt] { ... } - -# 59| [Parameter] -#-----| -1 -> (Annotations) -#-----| 0 -> [Annotation] Annot0k - -# 59| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 0 - -# 0| [IntegerLiteral] 0 - -# 59| [BlockStmt] { ... } - -# 57| [IntegerLiteral] 5 - -use.java: -# 1| [Class] use -#-----| -1 -> (Base Types) -#-----| 2 -> [Method] a -#-----| 3 -> [Method] annotationType -#-----| 4 -> [Class] Z - -# 1| [TypeAccess] Annot0k - -# 3| [Method] a -#-----| 1 -> (Annotations) -#-----| 3 -> [TypeAccess] int -#-----| 5 -> [BlockStmt] { ... } - -# 2| [Annotation] Override - -# 3| [BlockStmt] { ... } -#-----| 0 -> [ReturnStmt] return ... - -# 3| [TypeAccess] int - -# 3| [ReturnStmt] return ... -#-----| 0 -> [IntegerLiteral] 1 - -# 3| [IntegerLiteral] 1 - -# 6| [Method] annotationType -#-----| 1 -> (Annotations) -#-----| 3 -> [TypeAccess] Class -#-----| 5 -> [BlockStmt] { ... } - -# 5| [Annotation] Override - -# 6| [BlockStmt] { ... } -#-----| 0 -> [ReturnStmt] return ... - -# 6| [TypeAccess] Class -#-----| 0 -> [WildcardTypeAccess] ? ... - -# 6| [WildcardTypeAccess] ? ... -#-----| 0 -> [TypeAccess] Annotation - -# 6| [TypeAccess] Annotation - -# 7| [ReturnStmt] return ... -#-----| 0 -> [NullLiteral] null - -# 7| [NullLiteral] null - -# 14| [Class] Z -#-----| -3 -> (Annotations) - -# 10| [Annotation] Annot0j -#-----| 1 -> [IntegerLiteral] 1 - -# 10| [IntegerLiteral] 1 - -# 12| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 1 - -# 12| [IntegerLiteral] 1 - -# 11| [Annotation] Annot1j -#-----| 1 -> [IntegerLiteral] 1 -#-----| 2 -> [StringLiteral] "ac" -#-----| 3 -> [TypeLiteral] X.class -#-----| 4 -> [VarAccess] Y.B -#-----| 5 -> [ArrayInit] {...} -#-----| 6 -> [Annotation] Annot0j - -# 11| [IntegerLiteral] 1 - -# 11| [StringLiteral] "ac" - -# 11| [TypeLiteral] X.class -#-----| 0 -> [TypeAccess] X - -# 11| [TypeAccess] X - -# 11| [VarAccess] Y.B -#-----| -1 -> [TypeAccess] Y - -# 11| [TypeAccess] Y - -# 11| [ArrayInit] {...} -#-----| 3 -> [VarAccess] Y.C -#-----| 4 -> [VarAccess] Y.A - -# 11| [VarAccess] Y.C -#-----| -1 -> [TypeAccess] Y - -# 11| [TypeAccess] Y - -# 11| [VarAccess] Y.A -#-----| -1 -> [TypeAccess] Y - -# 11| [TypeAccess] Y - -# 11| [Annotation] Annot0j -#-----| 1 -> [IntegerLiteral] 2 - -# 11| [IntegerLiteral] 2 - -# 13| [Annotation] Annot1k -#-----| 1 -> [IntegerLiteral] 1 -#-----| 2 -> [StringLiteral] "ac" -#-----| 3 -> [TypeLiteral] X.class -#-----| 4 -> [VarAccess] Y.B -#-----| 5 -> [ArrayInit] {...} -#-----| 6 -> [Annotation] Annot0k - -# 13| [IntegerLiteral] 1 - -# 13| [StringLiteral] "ac" - -# 13| [TypeLiteral] X.class -#-----| 0 -> [TypeAccess] X - -# 13| [TypeAccess] X - -# 13| [VarAccess] Y.B -#-----| -1 -> [TypeAccess] Y - -# 13| [TypeAccess] Y - -# 13| [ArrayInit] {...} -#-----| 3 -> [VarAccess] Y.C -#-----| 4 -> [VarAccess] Y.A - -# 13| [VarAccess] Y.C -#-----| -1 -> [TypeAccess] Y - -# 13| [TypeAccess] Y - -# 13| [VarAccess] Y.A -#-----| -1 -> [TypeAccess] Y - -# 13| [TypeAccess] Y - -# 13| [Annotation] Annot0k -#-----| 1 -> [IntegerLiteral] 2 - -# 13| [IntegerLiteral] 2 - -#-----| (Base Types) -#-----| 0 -> [TypeAccess] Annot0k - -#-----| (Annotations) -#-----| 5 -> [Annotation] Target - -#-----| (Annotations) -#-----| 2 -> [Annotation] JvmName - -#-----| (Annotations) -#-----| 4 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k -#-----| 2 -> [Annotation] Annot1k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0k - -#-----| (Annotations) -#-----| 1 -> [Annotation] Override - -#-----| (Annotations) -#-----| 1 -> [Annotation] Override - -#-----| (Annotations) -#-----| 1 -> [Annotation] Annot0j -#-----| 2 -> [Annotation] Annot1j -#-----| 3 -> [Annotation] Annot0k -#-----| 4 -> [Annotation] Annot1k - -#-----| (Parameters) -#-----| 0 -> [Parameter] value - -#-----| (Parameters) -#-----| 0 -> [Parameter] a - -#-----| (Parameters) -#-----| 0 -> [Parameter] - -#-----| (Parameters) -#-----| 0 -> [Parameter] - -#-----| (Generic Parameters) -#-----| 0 -> [TypeVariable] T - Annot0j.java: # 0| [CompilationUnit] Annot0j -#-----| 1 -> [Interface] Annot0j - +# 1| 1: [Interface] Annot0j +# 2| 1: [Method] abc +# 2| 3: [TypeAccess] int Annot1j.java: # 0| [CompilationUnit] Annot1j -#-----| 1 -> [Interface] 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 -#-----| 1 -> [Class] DefKt -#-----| 2 -> [Interface] Annot0k -#-----| 3 -> [Interface] Annot1k -#-----| 4 -> [Class] X -#-----| 5 -> [Class] Y -#-----| 6 -> [Class] Z - +# 0| 1: [Class] DefKt +# 46| 2: [Method] fn +#-----| 2: (Generic Parameters) +# 46| 0: [TypeVariable] T +#-----| 4: (Parameters) +# 46| 0: [Parameter] a +# 46| 5: [BlockStmt] { ... } +# 47| 0: [ExprStmt] ; +# 47| 0: [MethodAccess] println(...) +# 47| -1: [TypeAccess] ConsoleKt +# 47| 0: [MethodAccess] a(...) +# 47| -1: [VarAccess] a +# 49| 1: [LocalVariableDeclStmt] var ...; +# 49| 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 +# 57| 5: [BlockStmt] { ... } +# 57| 0: [ReturnStmt] return ... +# 57| 0: [VarAccess] p +# 57| 4: [Method] setP +#-----| 4: (Parameters) +# 57| 0: [Parameter] +# 57| 5: [BlockStmt] { ... } +# 57| 0: [ExprStmt] ; +# 57| 0: [AssignExpr] ...=... +# 57| 0: [VarAccess] p +# 57| 1: [VarAccess] +# 59| 6: [ExtensionMethod] myExtension +#-----| 4: (Parameters) +# 59| 0: [Parameter] +# 59| 5: [BlockStmt] { ... } +# 5| 2: [Interface] Annot0k +#-----| -3: (Annotations) +# 5| 5: [Annotation] Target +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] CLASS +# 0| 1: [VarAccess] ANNOTATION_CLASS +# 0| 1: [VarAccess] TYPE_PARAMETER +# 0| 1: [VarAccess] PROPERTY +# 0| 1: [VarAccess] FIELD +# 0| 1: [VarAccess] LOCAL_VARIABLE +# 0| 1: [VarAccess] VALUE_PARAMETER +# 0| 1: [VarAccess] CONSTRUCTOR +# 0| 1: [VarAccess] FUNCTION +# 0| 1: [VarAccess] PROPERTY_GETTER +# 0| 1: [VarAccess] PROPERTY_SETTER +# 0| 1: [VarAccess] TYPE +# 0| 1: [VarAccess] FILE +# 0| 1: [VarAccess] TYPEALIAS +# 21| 1: [Method] a +# 23| 3: [Interface] Annot1k +#-----| -3: (Annotations) +# 23| 4: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 0 +# 25| 1: [Method] a +# 26| 2: [Method] b +# 27| 3: [Method] c +# 28| 4: [Method] d +# 29| 5: [Method] e +# 30| 6: [Method] f +# 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] values +# 0| 2: [Method] valueOf +#-----| 4: (Parameters) +# 0| 0: [Parameter] value +# 34| 4: [Constructor] Y +# 34| 5: [BlockStmt] { ... } +# 34| 0: [ExprStmt] ; +# 34| 0: [ClassInstanceExpr] new Enum(...) +# 34| -3: [TypeAccess] Unit +# 34| 0: [TypeAccess] Y +# 34| 1: [BlockStmt] { ... } +# 38| 6: [Class] Z +#-----| -3: (Annotations) +# 38| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 39| 2: [Annotation] Annot1k +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [StringLiteral] ab +# 0| 1: [TypeLiteral] X.class +# 0| 0: [TypeAccess] X +# 0| 1: [VarAccess] B +# 0| 1: [ArrayInit] {...} +# 0| 1: [VarAccess] C +# 0| 1: [VarAccess] A +# 0| 1: [Annotation] Annot0k +# 0| 1: [IntegerLiteral] 1 +# 42| 1: [Constructor] Z +# 41| 5: [BlockStmt] { ... } +# 42| 0: [SuperConstructorInvocationStmt] super(...) +# 42| 1: [BlockStmt] { ... } use.java: # 0| [CompilationUnit] use -#-----| 1 -> [Class] 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/classes.expected b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected index 6a60e04dd6f..9ef212e7840 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -19,14 +19,7 @@ annotations | 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:6:46:13 | Annot0k | def.kt:46:6:46:15 | T | 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 | @@ -36,7 +29,6 @@ annotations annotationValues | def.kt:0:0:0:0 | Annot0k | def.kt:0:0:0:0 | 1 | | 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 | @@ -45,14 +37,7 @@ annotationValues | 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 | ab | | 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:6:46:13 | 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" | From 24434ed0ffa505fd2c82da908439e8ed9e0f0bca Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 9 Nov 2022 16:49:16 +0000 Subject: [PATCH 073/136] Make annotation labelling consistent between Java and Kotlin This gives all annotations and expressions derived from them globally-significant and stable names, enabling the Kotlin and Java extractors to see the same annotation without introducing database conflicts. --- .../src/main/kotlin/KotlinFileExtractor.kt | 152 ++++++++++-------- 1 file changed, 88 insertions(+), 64 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index af8228856bc..0f44e2a30ef 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -459,19 +459,20 @@ open class KotlinFileExtractor( } private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { - for ((idx, constructorCall: IrConstructorCall) in c.annotations.withIndex()) { - extractAnnotation(constructorCall, parent, -1 - idx) + for ((idx, constructorCall: IrConstructorCall) in c.annotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { + extractAnnotation(constructorCall, parent, idx) } } private fun extractAnnotation( constructorCall: IrConstructorCall, parent: Label, - idx: Int + idx: Int, + contextLabel: String? = null ): Label { val t = useType(constructorCall.type) - - val id = tw.getLabelFor("@\"annotation_kotlin;{$parent};{${t.javaResult.id}}\"") + 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) @@ -484,9 +485,10 @@ open class KotlinFileExtractor( .filterIsInstance() .first { it.name == param.name } val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression - val exprId = extractAnnotationValueExpression(v, id, i) + val getterId = useFunction(prop.getter!!) + val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}") if (exprId != null) { - tw.writeAnnotValue(id, useFunction(prop.getter!!), exprId) + tw.writeAnnotValue(id, getterId, exprId) } } return id @@ -495,41 +497,45 @@ open class KotlinFileExtractor( private fun extractAnnotationValueExpression( v: IrExpression?, parent: Label, - idx: Int): Label? { + idx: Int, + contextLabel: String): Label? { + + fun exprId() = tw.getLabelFor("@\"annotationExpr;{$parent};$idx\"") return when (v) { is IrConst<*> -> { - extractConstant(v, parent, idx, null, null) + extractConstant(v, parent, idx, null, null, overrideId = exprId()) } is IrGetEnumValue -> { - extractEnumValue(v, parent, idx, null, null) + extractEnumValue(v, parent, idx, null, null, overrideId = exprId()) } is IrClassReference -> { - extractClassReference(v, parent, idx, null, null) + val classRefId = exprId() + val typeAccessId = tw.getLabelFor("@\"annotationExpr;{$classRefId};0\"") + extractClassReference(v, parent, idx, null, null, overrideId = classRefId, typeAccessOverrideId = typeAccessId, useUnboundType = true) } is IrConstructorCall -> { - extractAnnotation(v, parent, idx) + extractAnnotation(v, parent, idx, contextLabel) } is IrVararg -> { - val eId = tw.getFreshIdLabel() - val type = useType(v.type) - tw.writeExprs_arrayinit(eId, type.javaResult.id, parent, idx) - tw.writeExprsKotlinType(eId, type.kotlinResult.id) - tw.writeHasLocation(eId, tw.getLocation(v)) + tw.getLabelFor("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> + val type = useType(v.type) + 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 + 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, eId, index) - } } - - eId + extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index") + } } + } } // is IrErrorExpression // null @@ -3525,8 +3531,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) @@ -3534,8 +3540,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) @@ -3550,16 +3556,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() - } - private fun extractExpression(e: IrExpression, callable: Label, parent: StmtExprParent) { with("expression", e) { when(e) { @@ -4182,21 +4178,33 @@ open class KotlinFileExtractor( extractExpressionExpr(loop.condition, callable, id, 0, id) } + @Suppress("UNCHECKED_CAST") + private fun exprIdOrFresh(id: Label?) = id as? Label ?: tw.getFreshIdLabel() + + private fun toUnbound(t: IrType) = + when(t) { + is IrSimpleType -> t.classifier.typeWith() + else -> t + } + private fun extractClassReference( e: IrClassReference, parent: Label, idx: Int, enclosingCallable: Label?, - enclosingStmt: Label? + enclosingStmt: Label?, + overrideId: Label? = null, + typeAccessOverrideId: Label? = null, + useUnboundType: Boolean = false ) = - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val locId = tw.getLocation(e) - val type = useType(e.type) + val type = useType(if (useUnboundType) toUnbound(e.type) else 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) + extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt, overrideId = typeAccessOverrideId) } private fun extractEnumValue( @@ -4204,9 +4212,10 @@ open class KotlinFileExtractor( parent: Label, idx: Int, enclosingCallable: Label?, - enclosingStmt: Label? + enclosingStmt: Label?, + overrideId: Label? = null ) = - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_varaccess(id, type.javaResult.id, parent, idx) @@ -4223,6 +4232,16 @@ open class KotlinFileExtractor( } } + 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 @@ -4235,15 +4254,17 @@ open class KotlinFileExtractor( parent: Label, idx: Int, enclosingCallable: Label?, - enclosingStmt: 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) + extractConstantInteger(v, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId) } v is Long -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_longliteral(id, type.javaResult.id, parent, idx) @@ -4253,7 +4274,7 @@ open class KotlinFileExtractor( } } v is Float -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_floatingpointliteral(id, type.javaResult.id, parent, idx) @@ -4263,7 +4284,7 @@ open class KotlinFileExtractor( } } v is Double -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_doubleliteral(id, type.javaResult.id, parent, idx) @@ -4273,7 +4294,7 @@ open class KotlinFileExtractor( } } v is Boolean -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_booleanliteral(id, type.javaResult.id, parent, idx) @@ -4283,7 +4304,7 @@ open class KotlinFileExtractor( } } v is Char -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_characterliteral(id, type.javaResult.id, parent, idx) @@ -4293,7 +4314,7 @@ open class KotlinFileExtractor( } } v is String -> { - tw.getFreshIdLabel().also { id -> + exprIdOrFresh(overrideId).also { id -> val type = useType(e.type) val locId = tw.getLocation(e) tw.writeExprs_stringliteral(id, type.javaResult.id, parent, idx) @@ -4303,7 +4324,7 @@ open class KotlinFileExtractor( } } v == null -> { - extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt) + extractNull(e.type, tw.getLocation(e), parent, idx, enclosingCallable, enclosingStmt, overrideId = overrideId) } else -> { null.also { @@ -5157,11 +5178,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) @@ -5171,8 +5192,8 @@ 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) + 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) } @@ -5220,11 +5241,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 From 2fd8e61fe29a77216d421e263926b351629a3825 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 9 Nov 2022 16:57:39 +0000 Subject: [PATCH 074/136] Add test of Java/Kotlin annotation naming consistency --- .../PrintAst.expected | 53 +++++++++++++++++++ .../annotation-id-consistency/PrintAst.qlref | 1 + .../annotation-id-consistency/User.java | 7 +++ .../kotlin/annotation-id-consistency/test.kt | 10 ++++ .../kotlin/annotation-id-consistency/test.py | 5 ++ .../kotlin/annotation-id-consistency/x.kt | 3 ++ 6 files changed, 79 insertions(+) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.expected create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.qlref create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/User.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.py create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt 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..da7d61a4ee3 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/PrintAst.expected @@ -0,0 +1,53 @@ +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 +test.kt: +# 0| [CompilationUnit] test +# 3| 1: [Interface] Ann1 +# 3| 1: [Method] x +# 3| 2: [Method] y +# 5| 2: [Interface] Ann2 +# 5| 1: [Method] z +# 5| 2: [Method] w +# 5| 3: [Method] v +# 5| 4: [Method] u +# 7| 3: [Interface] Ann3 +# 7| 1: [Method] a +# 9| 4: [Class] Annotated +#-----| -3: (Annotations) +# 9| 2: [Annotation] Ann1 +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [Annotation] Ann2 +# 0| 1: [StringLiteral] "Hello" +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 0| 1: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 2 +# 10| 1: [Constructor] Annotated +# 9| 5: [BlockStmt] { ... } +# 9| 0: [SuperConstructorInvocationStmt] super(...) +# 10| 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..7061beedb93 --- /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(); + } + +} 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..daef571e62d --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt @@ -0,0 +1,10 @@ +import kotlin.reflect.KClass + +annotation class Ann1(val x: Int, val y: Ann2) { } + +annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: Array) { } + +annotation class Ann3(val a: Int) { } + +@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)))) +class Annotated { } 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..8ceac659f1d --- /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"], lang="java") diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt new file mode 100644 index 00000000000..5ca8afcf8e7 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt @@ -0,0 +1,3 @@ +import kotlin.reflect.KClass + +fun f(x: KClass<*>) = x From d7213d2d82188da7377bad924c02839797e5e85c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 9 Nov 2022 17:24:40 +0000 Subject: [PATCH 075/136] Only convert KClass -> Class in annotation context --- .../src/main/kotlin/KotlinFileExtractor.kt | 9 +++++---- .../kotlin-extractor/src/main/kotlin/utils/ClassNames.kt | 8 +------- .../kotlin/annotation-id-consistency/PrintAst.expected | 6 ++++++ .../kotlin/annotation-id-consistency/test.kt | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 0f44e2a30ef..84c5c721ed0 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -512,14 +512,14 @@ open class KotlinFileExtractor( is IrClassReference -> { val classRefId = exprId() val typeAccessId = tw.getLabelFor("@\"annotationExpr;{$classRefId};0\"") - extractClassReference(v, parent, idx, null, null, overrideId = classRefId, typeAccessOverrideId = typeAccessId, useUnboundType = true) + extractClassReference(v, parent, idx, null, null, overrideId = classRefId, typeAccessOverrideId = typeAccessId, useJavaLangClassType = true) } is IrConstructorCall -> { extractAnnotation(v, parent, idx, contextLabel) } is IrVararg -> { tw.getLabelFor("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> - val type = useType(v.type) + val type = useType(kClassToJavaClass(v.type)) tw.writeExprs_arrayinit(arrayId, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(arrayId, type.kotlinResult.id) tw.writeHasLocation(arrayId, tw.getLocation(v)) @@ -4195,11 +4195,12 @@ open class KotlinFileExtractor( enclosingStmt: Label?, overrideId: Label? = null, typeAccessOverrideId: Label? = null, - useUnboundType: Boolean = false + useJavaLangClassType: Boolean = false ) = exprIdOrFresh(overrideId).also { id -> val locId = tw.getLocation(e) - val type = useType(if (useUnboundType) toUnbound(e.type) else e.type) + 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) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt index ccb649e9561..0bfed4a23c3 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt @@ -120,10 +120,4 @@ fun getContainingClassOrSelf(decl: IrDeclaration): IrClass? { } fun getJavaEquivalentClassId(c: IrClass) = - c.fqNameWhenAvailable?.toUnsafe()?.let { - if (it.asString() == "kotlin.reflect.KClass") { - ClassId.fromString("java.lang.Class") - } else { - JavaToKotlinClassMap.mapKotlinToJava(it) - } - } + c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) } 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 index da7d61a4ee3..89d9523db96 100644 --- 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 @@ -28,6 +28,7 @@ test.kt: # 5| 2: [Method] w # 5| 3: [Method] v # 5| 4: [Method] u +# 5| 5: [Method] t # 7| 3: [Interface] Ann3 # 7| 1: [Method] a # 9| 4: [Class] Annotated @@ -47,6 +48,11 @@ test.kt: # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 2 +# 0| 1: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [TypeLiteral] int.class +# 0| 0: [TypeAccess] int # 10| 1: [Constructor] Annotated # 9| 5: [BlockStmt] { ... } # 9| 0: [SuperConstructorInvocationStmt] super(...) 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 index daef571e62d..c897d8faf15 100644 --- 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 @@ -2,9 +2,9 @@ import kotlin.reflect.KClass annotation class Ann1(val x: Int, val y: Ann2) { } -annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: Array) { } +annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: Array, val t: Array>) { } annotation class Ann3(val a: Int) { } -@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)))) +@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class))) class Annotated { } From 14a47f628ceca43bcecc855d333bb70d9fb3ed98 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 9 Nov 2022 18:42:23 +0000 Subject: [PATCH 076/136] Fixup: remove unneeded test file --- .../all-platforms/kotlin/annotation-id-consistency/x.kt | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt diff --git a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt deleted file mode 100644 index 5ca8afcf8e7..00000000000 --- a/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/x.kt +++ /dev/null @@ -1,3 +0,0 @@ -import kotlin.reflect.KClass - -fun f(x: KClass<*>) = x From 06133e74a553df545b7f21aebb85af3bf5804be4 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 9 Nov 2022 19:07:27 +0000 Subject: [PATCH 077/136] Handle generic annotations --- .../src/main/kotlin/KotlinFileExtractor.kt | 18 ++++++++----- .../PrintAst.expected | 25 ++++++++++++++----- .../kotlin/annotation-id-consistency/test.kt | 3 +++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 84c5c721ed0..b1784547889 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -470,7 +470,8 @@ open class KotlinFileExtractor( idx: Int, contextLabel: String? = null ): Label { - val t = useType(constructorCall.type) + // 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) @@ -485,8 +486,9 @@ open class KotlinFileExtractor( .filterIsInstance() .first { it.name == param.name } val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression - val getterId = useFunction(prop.getter!!) - val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}") + val getter = prop.getter!! + val getterId = useFunction(getter) + val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType) if (exprId != null) { tw.writeAnnotValue(id, getterId, exprId) } @@ -498,7 +500,8 @@ open class KotlinFileExtractor( v: IrExpression?, parent: Label, idx: Int, - contextLabel: String): Label? { + contextLabel: String, + contextType: IrType?): Label? { fun exprId() = tw.getLabelFor("@\"annotationExpr;{$parent};$idx\"") @@ -519,7 +522,10 @@ open class KotlinFileExtractor( } is IrVararg -> { tw.getLabelFor("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> - val type = useType(kClassToJavaClass(v.type)) + // 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. + 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)) @@ -533,7 +539,7 @@ open class KotlinFileExtractor( null } } - extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index") + extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null) } } } } 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 index 89d9523db96..d1e11f8611b 100644 --- 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 @@ -31,9 +31,14 @@ test.kt: # 5| 5: [Method] t # 7| 3: [Interface] Ann3 # 7| 1: [Method] a -# 9| 4: [Class] Annotated +# 9| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation +#-----| -2: (Generic Parameters) +# 9| 0: [TypeVariable] T +# 9| 1: [Method] x +# 9| 2: [Method] y +# 11| 6: [Class] Annotated #-----| -3: (Annotations) -# 9| 2: [Annotation] Ann1 +# 11| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -53,7 +58,15 @@ test.kt: # 0| 0: [TypeAccess] String # 0| 1: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 10| 1: [Constructor] Annotated -# 9| 5: [BlockStmt] { ... } -# 9| 0: [SuperConstructorInvocationStmt] super(...) -# 10| 1: [BlockStmt] { ... } +# 12| 3: [Annotation] GenericAnnotation<> +# 13| 1: [Constructor] Annotated +# 11| 5: [BlockStmt] { ... } +# 11| 0: [SuperConstructorInvocationStmt] super(...) +# 13| 1: [BlockStmt] { ... } +# 0| [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String 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 index c897d8faf15..fe5dd9b1b76 100644 --- 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 @@ -6,5 +6,8 @@ annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: A annotation class Ann3(val a: Int) { } +annotation class GenericAnnotation(val x: KClass, val y: Array>) { } + @Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class))) +@GenericAnnotation(String::class, arrayOf(String::class, String::class)) class Annotated { } From 8781366fbe78524acf6d0db4d8da2b186a485508 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 11:27:21 +0000 Subject: [PATCH 078/136] Only extract function annotations for unbound types Note however this includes extracting annotations for external types, unlike the situation for function bodies. --- .../src/main/kotlin/ExternalDeclExtractor.kt | 2 +- .../src/main/kotlin/KotlinFileExtractor.kt | 40 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) 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/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b1784547889..9cf9b5790a8 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -91,7 +91,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 +148,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 +163,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 +173,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 } @@ -406,8 +406,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 -> {} } } @@ -604,11 +604,11 @@ open class KotlinFileExtractor( .filterIsInstance() .map { val getter = it.getter!! - val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, null, listOf()) + val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, extractAnnotations = true, null, listOf()) tw.writeIsAnnotElem(label!!.cast()) } } else { - c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) } + c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies, extractAnnotations = true) } if (extractStaticInitializer) extractStaticInitializer(c, { id }) extractJvmStaticProxyMethods(c, id, extractPrivateMembers, extractFunctionBodies) @@ -665,7 +665,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) { @@ -1010,7 +1010,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, modality = Modality.OPEN)).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) @@ -1051,7 +1051,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) @@ -1060,7 +1060,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) @@ -1196,7 +1196,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) { @@ -1282,7 +1282,7 @@ 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 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 { @@ -1424,7 +1424,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 @@ -1446,7 +1446,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) { @@ -1463,7 +1463,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) { @@ -1528,7 +1528,7 @@ open class KotlinFileExtractor( } ee.correspondingClass?.let { - extractDeclaration(it, extractPrivateMembers, extractFunctionBodies) + extractDeclaration(it, extractPrivateMembers, extractFunctionBodies, extractAnnotations = true) } extractAnnotations(ee, id) @@ -5503,7 +5503,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), modality = Modality.FINAL)) + 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()) { @@ -5685,7 +5685,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 } From 26540111ce95b89fcf5897aa689b3acb5c094c4c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 11:29:04 +0000 Subject: [PATCH 079/136] Factor out common code for referencing an external type --- .../src/main/kotlin/KotlinFileExtractor.kt | 72 +++++-------------- .../src/main/kotlin/KotlinUsesExtractor.kt | 26 +++---- 2 files changed, 28 insertions(+), 70 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 9cf9b5790a8..3d73460ad43 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1903,11 +1903,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() @@ -2269,11 +2265,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) } @@ -2319,11 +2311,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 { @@ -2347,11 +2335,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 { @@ -2363,11 +2347,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) } @@ -4633,6 +4613,8 @@ open class KotlinFileExtractor( } } + private val propertyRefType by lazy { referenceExternalClass("kotlin.jvm.internal.PropertyReference")?.typeWith() } + private fun extractPropertyReference( exprKind: String, propertyReferenceExpr: IrCallableReference, @@ -4696,8 +4678,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) @@ -4791,6 +4772,8 @@ open class KotlinFileExtractor( } } + private val functionRefType by lazy { referenceExternalClass("kotlin.jvm.internal.FunctionReference")?.typeWith() } + private fun extractFunctionReference( functionReferenceExpr: IrFunctionReference, parent: StmtExprParent, @@ -4905,8 +4888,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. @@ -4952,34 +4934,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, 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) { From f7d2644d74cce4373f77f13a1e168e27a48b6ba7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 11:30:36 +0000 Subject: [PATCH 080/136] Re-enable extracting most annotations --- .../src/main/kotlin/KotlinFileExtractor.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 3d73460ad43..2ed9aaf534c 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -238,7 +238,7 @@ open class KotlinFileExtractor( addModifiers(id, "out") } - //extractAnnotations(tp, id) + extractAnnotations(tp, id) return id } } @@ -832,7 +832,7 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) - //extractAnnotations(vp, id) + extractAnnotations(vp, id) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -1372,7 +1372,8 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) - //extractAnnotations(f, id) + if (extractAnnotations) + extractAnnotations(f, id) return id } From 9b3c07c32b9ef5d4f155680c0cd7c8171dbb8b90 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 11:30:59 +0000 Subject: [PATCH 081/136] Add annotation class meta-annotations per classes' expected JVM lowering --- .../src/main/kotlin/KotlinFileExtractor.kt | 198 +++++++++++++++++- 1 file changed, 193 insertions(+), 5 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 2ed9aaf534c..37e997dbdef 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -9,22 +9,29 @@ import com.semmle.extractor.java.OdasaOutput import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.jvm.ir.getAnnotationRetention +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention +import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget 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.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.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaMethod @@ -34,7 +41,9 @@ 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.lang.annotation.ElementType import java.util.* import kotlin.collections.ArrayList @@ -458,12 +467,16 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { - for ((idx, constructorCall: IrConstructorCall) in c.annotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { + private fun extractAnnotations(annotations: List, parent: Label) { + for ((idx, constructorCall: IrConstructorCall) in annotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { extractAnnotation(constructorCall, parent, idx) } } + private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { + extractAnnotations(c.annotations, parent) + } + private fun extractAnnotation( constructorCall: IrConstructorCall, parent: Label, @@ -559,6 +572,175 @@ open class KotlinFileExtractor( } } + private val javaAnnotationTargetElementType by lazy { referenceExternalClass("java.lang.annotation.ElementType") } + + private val javaAnnotationTarget by lazy { referenceExternalClass("java.lang.annotation.Target") } + + // 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 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") + ) + } + } + } + + // TODO: find out if we can spot when we're building for JVM <= 7 and omit the Java 8-only targets in that case. + private fun getAnnotationTargetMap() = 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 { referenceExternalClass("java.lang.annotation.Retention") } + private val javaAnnotationRetentionPolicy by lazy { 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 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 { referenceExternalClass("java.lang.annotation.Repeatable") } + + // Taken from AdditionalClassAnnotationLowering.kt + private fun generateRepeatableAnnotation(irClass: IrClass): IrConstructorCall? { + if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) || + irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) + ) return null + + val repeatableConstructor = javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull() ?: return null + + val containerClass = + irClass.declarations.singleOrNull { + it is IrClass && it.name.asString() == JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME + } as IrClass? ?: return null + 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 { 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 + ) + } + + private fun generateJavaMetaAnnotations(c: IrClass) = + // This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend. + listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c), generateDocumentedAnnotation(c)) + fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label { with("class source", c) { DeclarationStackAdjuster(c).use { @@ -640,7 +822,13 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(c, id) - extractAnnotations(c, id) + val additionalAnnotations = + if (c.kind == ClassKind.ANNOTATION_CLASS && c.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) + generateJavaMetaAnnotations(c) + else + listOf() + + extractAnnotations(c.annotations + additionalAnnotations, id) if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) From df90fc1a80f242546d7a1071bfe57bf5cf1cabf8 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 14:01:40 +0000 Subject: [PATCH 082/136] Disable type parameter annotation extraction pending a database change --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 37e997dbdef..5deb44ff278 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -247,7 +247,8 @@ open class KotlinFileExtractor( addModifiers(id, "out") } - extractAnnotations(tp, id) + // extractAnnotations(tp, id) + // TODO: introduce annotations once they can be disambiguated from bounds, which are also child expressions. return id } } From d530817afc8f8fc984566bdb7fd798eba7206691 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 14:02:15 +0000 Subject: [PATCH 083/136] Accept annotation_classes test changes --- java/ql/lib/semmle/code/java/PrintAst.qll | 6 +- .../annotation_classes/PrintAst.expected | 141 ++++++++++++++---- .../annotation_classes/classes.expected | 21 ++- .../annotation_classes/classes.ql | 2 +- .../library-tests/annotation_classes/def.kt | 3 + 5 files changed, 141 insertions(+), 32 deletions(-) diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 3093c9b2643..802ba19030b 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -677,10 +677,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/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 18c14a30a4f..fc1d83bdc2b 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -23,10 +23,18 @@ 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(...) @@ -43,43 +51,102 @@ def.kt: # 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] p -# 57| 4: [Method] setP +# 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] p +# 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) -# 5| 5: [Annotation] Target +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 0| 2: [Annotation] Target # 0| 1: [ArrayInit] {...} -# 0| 1: [VarAccess] CLASS -# 0| 1: [VarAccess] ANNOTATION_CLASS -# 0| 1: [VarAccess] TYPE_PARAMETER -# 0| 1: [VarAccess] PROPERTY -# 0| 1: [VarAccess] FIELD -# 0| 1: [VarAccess] LOCAL_VARIABLE -# 0| 1: [VarAccess] VALUE_PARAMETER -# 0| 1: [VarAccess] CONSTRUCTOR -# 0| 1: [VarAccess] FUNCTION -# 0| 1: [VarAccess] PROPERTY_GETTER -# 0| 1: [VarAccess] PROPERTY_SETTER -# 0| 1: [VarAccess] TYPE -# 0| 1: [VarAccess] FILE -# 0| 1: [VarAccess] TYPEALIAS +# 0| 1: [VarAccess] ElementType.TYPE +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.FIELD +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.METHOD +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.PARAMETER +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.CONSTRUCTOR +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.LOCAL_VARIABLE +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.ANNOTATION_TYPE +# 0| -1: [TypeAccess] ElementType +# 0| 1: [VarAccess] ElementType.TYPE_PARAMETER +# 0| -1: [TypeAccess] ElementType +# 0| 1: [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| 1: [VarAccess] AnnotationTarget.ANNOTATION_CLASS +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.TYPE_PARAMETER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.PROPERTY +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.FIELD +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.LOCAL_VARIABLE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.VALUE_PARAMETER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.CONSTRUCTOR +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.FUNCTION +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.PROPERTY_GETTER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.PROPERTY_SETTER +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.TYPE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.FILE +# 0| -1: [TypeAccess] AnnotationTarget +# 0| 1: [VarAccess] AnnotationTarget.TYPEALIAS +# 0| -1: [TypeAccess] AnnotationTarget # 21| 1: [Method] a +#-----| 1: (Annotations) +# 21| 1: [Annotation] JvmName +# 0| 1: [StringLiteral] "a" # 23| 3: [Interface] Annot1k #-----| -3: (Annotations) -# 23| 4: [Annotation] Annot0k +# 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 # 26| 2: [Method] b @@ -93,33 +160,57 @@ def.kt: # 33| 0: [SuperConstructorInvocationStmt] super(...) # 33| 1: [BlockStmt] { ... } # 34| 5: [Class] Y -# 0| 2: [Method] values # 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] Unit +# 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| 1: [StringLiteral] ab +# 0| 1: [StringLiteral] "ab" # 0| 1: [TypeLiteral] X.class # 0| 0: [TypeAccess] X -# 0| 1: [VarAccess] B +# 0| 1: [VarAccess] Y.B +# 0| -1: [TypeAccess] Y # 0| 1: [ArrayInit] {...} -# 0| 1: [VarAccess] C -# 0| 1: [VarAccess] A +# 0| 1: [VarAccess] Y.C +# 0| -1: [TypeAccess] Y +# 0| 1: [VarAccess] Y.A +# 0| -1: [TypeAccess] Y # 0| 1: [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] { ... } 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 9ef212e7840..b04dd33d2e7 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.expected @@ -14,12 +14,17 @@ annotationDeclarations | 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 -| annotation_classes.testproj/test.class.files/Annot1k.class:0:0:0:0 | Annot0k | def.kt:23:1:31:1 | Annot1k | def.kt:5:1:21:60 | Annot0k | | 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 | @@ -28,16 +33,26 @@ annotations | 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 | B | | 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 | ab | +| 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" | 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 fc3db6f0c02..936165cf023 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql +++ b/java/ql/test/kotlin/library-tests/annotation_classes/classes.ql @@ -16,5 +16,5 @@ query predicate annotations(Annotation a, Element e, AnnotationType at) { } query predicate annotationValues(Annotation a, Expr v) { - a.getAValue() = v and v.getFile().isSourceFile() + 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 f499d1026fc..2fb107c1263 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt +++ b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt @@ -60,3 +60,6 @@ fun @receiver:Annot0k String.myExtension() { } @Annot0k typealias AAA = Z + +// Diagnostic Matches: Incomplete annotation: @kotlin.annotation.Target(%) +// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(%) From 0446145a675ed337bce54865ced3dc5f85931214 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 7 Dec 2022 18:25:39 +0000 Subject: [PATCH 084/136] Accept test changes These are due to changing string literal representation, omitting empty annotations blocks, and changes to how annotation classes are represented in the database. --- .../collection-literals/PrintAst.expected | 87 ++----------------- .../exprs/CONSISTENCY/cfgDeadEnds.expected | 1 - .../jvmoverloads-annotation/PrintAst.expected | 20 +++++ .../jvmstatic-annotation/PrintAst.expected | 12 +++ .../parameter-defaults/PrintAst.expected | 2 + 5 files changed, 40 insertions(+), 82 deletions(-) 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..ea5abd8c6e8 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,9 @@ 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 -# 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| 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 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy +# 1| 1: [Method] arr1 +# 1| 2: [Method] 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/jvmoverloads-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected index a1d0808d7a9..f169bb49418 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] @@ -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 @@ -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] @@ -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/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/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 972e826cdca..4f0b6e30c98 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -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 From 0146d8229a92d6d7aab80cbc617bd6ad1dcd6f36 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 11 Nov 2022 18:21:19 +0000 Subject: [PATCH 085/136] Accept more test changes due to string quoting and the Java extractor ignoring the Metadata annotation --- java/ql/test/kotlin/library-tests/generics-location/generics.kt | 1 - .../library-tests/internal-constructor-called-from-java/test.kt | 1 - java/ql/test/kotlin/library-tests/internal-public-alias/test.kt | 1 - 3 files changed, 3 deletions(-) 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 } - From 9e0eb56d775b73e0b154dc3cc9bbfee834ca0ea9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 12:28:48 +0000 Subject: [PATCH 086/136] Extract repeatable annotation container types, including synthetic containers --- .../main/kotlin/KotlinExtractorExtension.kt | 1 + .../src/main/kotlin/KotlinFileExtractor.kt | 126 +++++++++++++++++- 2 files changed, 121 insertions(+), 6 deletions(-) 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 5deb44ff278..5adaa26a132 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -7,6 +7,7 @@ import com.github.codeql.utils.versions.functionN import com.github.codeql.utils.versions.isUnderscoreParameter import com.semmle.extractor.java.OdasaOutput import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.jvm.ir.getAnnotationRetention @@ -22,6 +23,7 @@ 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.* @@ -39,6 +41,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -468,8 +471,65 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } + // Adapted from RepeatedAnnotationLowering.kt + private fun groupRepeatableAnnotations(annotations: List): List { + if (annotations.size < 2) return annotations + + val annotationsByClass = annotations.groupByTo(mutableMapOf()) { it.symbol.owner.constructedClass } + if (annotationsByClass.values.none { it.size > 1 }) return annotations + + val result = mutableListOf() + for (annotation in annotations) { + val annotationClass = annotation.symbol.owner.constructedClass + val grouped = annotationsByClass.remove(annotationClass) ?: continue + if (grouped.size < 2) { + result.add(grouped.single()) + continue + } + + val containerClass = getOrCreateContainerClass(annotationClass) + if (containerClass != null) + result.add(wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)) + 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.isAnnotation(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() + return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerClass.primaryConstructor!!.symbol).apply { + putValueArgument( + 0, + IrVarargImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + pluginContext.irBuiltIns.arrayClass.typeWith(annotationType), + annotationType, + entries + ) + ) + } + } + private fun extractAnnotations(annotations: List, parent: Label) { - for ((idx, constructorCall: IrConstructorCall) in annotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { + val groupedAnnotations = groupRepeatableAnnotations(annotations) + for ((idx, constructorCall: IrConstructorCall) in groupedAnnotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { extractAnnotation(constructorCall, parent, idx) } } @@ -699,8 +759,62 @@ open class KotlinFileExtractor( } private val javaAnnotationRepeatable by lazy { referenceExternalClass("java.lang.annotation.Repeatable") } + private val kotlinAnnotationRepeatableContainer by lazy { referenceExternalClass("kotlin.jvm.internal.RepeatableContainer") } - // Taken from AdditionalClassAnnotationLowering.kt + // Taken from JvmCachedDeclarations.kt + private fun getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass: IrClass) = + globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(annotationClass) { + val containerClass = pluginContext.irFactory.buildClass { + kind = ClassKind.ANNOTATION_CLASS + name = Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME) + }.apply { + createImplicitParameterDeclarationWithWrappedDescriptor() + parent = annotationClass + superTypes = listOf(pluginContext.irBuiltIns.annotationType) + } + + val propertyName = Name.identifier("value") + val propertyType = pluginContext.irBuiltIns.arrayClass.typeWith(annotationClass.typeWith()) + + containerClass.addConstructor { + isPrimary = true + }.apply { + addValueParameter(propertyName, propertyType) + } + + containerClass.addProperty { + name = propertyName + }.apply property@{ + backingField = pluginContext.irFactory.buildField { + name = propertyName + type = propertyType + }.apply { + parent = containerClass + correspondingPropertySymbol = this@property.symbol + } + addDefaultGetter(containerClass, pluginContext.irBuiltIns) + } + + val repeatableContainerAnnotation = kotlinAnnotationRepeatableContainer?.let { it.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): IrConstructorCall? { if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) || irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) @@ -708,10 +822,10 @@ open class KotlinFileExtractor( val repeatableConstructor = javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull() ?: return null - val containerClass = - irClass.declarations.singleOrNull { - it is IrClass && it.name.asString() == JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME - } as IrClass? ?: 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. + extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true) + val containerReference = IrClassReferenceImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType), containerClass.symbol, containerClass.defaultType From eaa9595ea2e684f6e85e0f629a0dbdc483d36657 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 12:37:20 +0000 Subject: [PATCH 087/136] Restore type-accesses to annotation methods; accept test changes. --- .../src/main/kotlin/KotlinFileExtractor.kt | 2 +- .../PrintAst.expected | 77 ++----------------- .../test.expected | 26 ------- 3 files changed, 9 insertions(+), 96 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 5adaa26a132..821ae798c6c 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -901,7 +901,7 @@ open class KotlinFileExtractor( .filterIsInstance() .map { val getter = it.getter!! - val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, extractAnnotations = true, null, listOf()) + val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = true, extractAnnotations = true, null, listOf()) tw.writeIsAnnotElem(label!!.cast()) } } else { 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 | From d96bca071d7371e30b58c6d9ffd33483c9a1f5ce Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 15:15:28 +0000 Subject: [PATCH 088/136] Add test for repeatable annotations --- .../JavaDefinedContainer.java | 5 +++++ .../JavaDefinedRepeatable.java | 3 +++ .../kotlin/repeatable-annotations/JavaUser.java | 7 +++++++ .../kotlin/repeatable-annotations/lib.kt | 7 +++++++ .../kotlin/repeatable-annotations/test.expected | 15 +++++++++++++++ .../kotlin/repeatable-annotations/test.kt | 12 ++++++++++++ .../kotlin/repeatable-annotations/test.py | 7 +++++++ .../kotlin/repeatable-annotations/test.ql | 11 +++++++++++ 8 files changed, 67 insertions(+) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedContainer.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaDefinedRepeatable.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/lib.kt create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.kt create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py create mode 100644 java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.ql 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..959becd2682 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java @@ -0,0 +1,7 @@ +@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..ff9e747cac5 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected @@ -0,0 +1,15 @@ +| JavaUser.java:7:14:7:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} | +| JavaUser.java:7:14:7:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | JavaDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} | +| JavaUser.java:7:14:7: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 | RetentionPolicy.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 | RetentionPolicy.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 | RetentionPolicy.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..fa0700cea28 --- /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(["javac JavaUser.java -cp out -d out2", "kotlinc test.kt -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 From 6d5f962c56d823fe9f561325dba494bca0086f7a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 15:45:51 +0000 Subject: [PATCH 089/136] Accept test changes (implicit annotations, restoration of annotation type accesses) --- .../PrintAst.expected | 37 ++++++++++++++++++- .../annotation_classes/PrintAst.expected | 9 +++++ .../collection-literals/PrintAst.expected | 3 ++ 3 files changed, 47 insertions(+), 2 deletions(-) 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 index d1e11f8611b..bf14cd7523e 100644 --- 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 @@ -21,24 +21,57 @@ User.java: test.kt: # 0| [CompilationUnit] test # 3| 1: [Interface] Ann1 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy # 3| 1: [Method] x +# 3| 3: [TypeAccess] int # 3| 2: [Method] y +# 3| 3: [TypeAccess] Ann2 # 5| 2: [Interface] Ann2 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy # 5| 1: [Method] z +# 5| 3: [TypeAccess] String # 5| 2: [Method] w +# 5| 3: [TypeAccess] Class +# 5| 0: [WildcardTypeAccess] ? ... # 5| 3: [Method] v +# 5| 3: [TypeAccess] int[] # 5| 4: [Method] u +# 5| 3: [TypeAccess] Ann3[] +# 5| 0: [TypeAccess] Ann3 # 5| 5: [Method] t +# 5| 3: [TypeAccess] Class[] +# 5| 0: [TypeAccess] Class +# 5| 0: [WildcardTypeAccess] ? ... # 7| 3: [Interface] Ann3 +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy # 7| 1: [Method] a +# 7| 3: [TypeAccess] int # 9| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation +#-----| -3: (Annotations) +# 0| 1: [Annotation] Retention +# 0| 1: [VarAccess] RetentionPolicy.RUNTIME +# 0| -1: [TypeAccess] RetentionPolicy #-----| -2: (Generic Parameters) # 9| 0: [TypeVariable] T # 9| 1: [Method] x +# 9| 3: [TypeAccess] Class +# 9| 0: [TypeAccess] T # 9| 2: [Method] y +# 9| 3: [TypeAccess] Class[] +# 9| 0: [TypeAccess] Class +# 9| 0: [TypeAccess] T # 11| 6: [Class] Annotated #-----| -3: (Annotations) -# 11| 2: [Annotation] Ann1 +# 11| 1: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -58,7 +91,7 @@ test.kt: # 0| 0: [TypeAccess] String # 0| 1: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 12| 3: [Annotation] GenericAnnotation<> +# 12| 2: [Annotation] GenericAnnotation<> # 13| 1: [Constructor] Annotated # 11| 5: [BlockStmt] { ... } # 11| 0: [SuperConstructorInvocationStmt] super(...) diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index fc1d83bdc2b..79bc39c4392 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -141,6 +141,7 @@ def.kt: #-----| 1: (Annotations) # 21| 1: [Annotation] JvmName # 0| 1: [StringLiteral] "a" +# 21| 3: [TypeAccess] int # 23| 3: [Interface] Annot1k #-----| -3: (Annotations) # 0| 1: [Annotation] Retention @@ -149,11 +150,19 @@ def.kt: # 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] { ... } 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 ea5abd8c6e8..cbcabc82bd5 100644 --- a/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/collection-literals/PrintAst.expected @@ -6,4 +6,7 @@ test.kt: # 0| 1: [VarAccess] RetentionPolicy.RUNTIME # 0| -1: [TypeAccess] RetentionPolicy # 1| 1: [Method] arr1 +# 1| 3: [TypeAccess] String[] +# 1| 0: [TypeAccess] String # 1| 2: [Method] arr2 +# 1| 3: [TypeAccess] int[] From 73df3166ebd8ba172409c3dc2d2fb1d58d73aac3 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 15:49:45 +0000 Subject: [PATCH 090/136] Test varargs annotation --- .../PrintAst.expected | 55 ++++++++++++++++--- .../kotlin/annotation-id-consistency/test.kt | 9 +++ 2 files changed, 57 insertions(+), 7 deletions(-) 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 index bf14cd7523e..fa380ef7b00 100644 --- 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 @@ -69,9 +69,50 @@ test.kt: # 9| 3: [TypeAccess] Class[] # 9| 0: [TypeAccess] Class # 9| 0: [TypeAccess] T -# 11| 6: [Class] Annotated +# 11| 6: [Interface] VarargAnnotation #-----| -3: (Annotations) -# 11| 1: [Annotation] Ann1 +# 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 +# 11| 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 +# 12| 2: [Method] x +# 12| 3: [TypeAccess] int[] +# 14| 7: [Class] Annotated +#-----| -3: (Annotations) +# 0| 1: [Annotation] Container +# 0| 1: [ArrayInit] {...} +# 16| 1: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 17| 2: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 18| 3: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 19| 4: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 20| 5: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 14| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -91,11 +132,11 @@ test.kt: # 0| 0: [TypeAccess] String # 0| 1: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 12| 2: [Annotation] GenericAnnotation<> -# 13| 1: [Constructor] Annotated -# 11| 5: [BlockStmt] { ... } -# 11| 0: [SuperConstructorInvocationStmt] super(...) -# 13| 1: [BlockStmt] { ... } +# 15| 3: [Annotation] GenericAnnotation<> +# 21| 1: [Constructor] Annotated +# 14| 5: [BlockStmt] { ... } +# 14| 0: [SuperConstructorInvocationStmt] super(...) +# 21| 1: [BlockStmt] { ... } # 0| [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [ArrayInit] {...} 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 index fe5dd9b1b76..50b87181a6f 100644 --- 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 @@ -8,6 +8,15 @@ annotation class Ann3(val a: Int) { } annotation class GenericAnnotation(val x: KClass, val y: Array>) { } +@Repeatable +annotation class VarargAnnotation(vararg val x: Int) { } + @Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class))) @GenericAnnotation(String::class, arrayOf(String::class, String::class)) +@VarargAnnotation +@VarargAnnotation(1) +@VarargAnnotation(1, 2) +@VarargAnnotation(*[1, 2, 3]) +@VarargAnnotation(*intArrayOf(1, 2, 3)) class Annotated { } + From ca27f9516adce6277cb090c3671030571a9970f4 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 16:19:21 +0000 Subject: [PATCH 091/136] Replace uses of !! operator --- .../src/main/kotlin/KotlinFileExtractor.kt | 83 ++++++++++++------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 821ae798c6c..0783c7fdf1e 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -512,18 +512,24 @@ open class KotlinFileExtractor( annotationClass: IrClass, containerClass: IrClass, entries: List, - ): IrConstructorCall { + ): IrConstructorCall? { val annotationType = annotationClass.typeWith() - return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerClass.primaryConstructor!!.symbol).apply { - putValueArgument( - 0, - IrVarargImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, - pluginContext.irBuiltIns.arrayClass.typeWith(annotationType), - annotationType, - entries + 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 + ) ) - ) + } } } @@ -560,11 +566,15 @@ open class KotlinFileExtractor( .filterIsInstance() .first { it.name == param.name } val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression - val getter = prop.getter!! - val getterId = useFunction(getter) - val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType) - if (exprId != null) { - tw.writeAnnotValue(id, getterId, exprId) + 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) + if (exprId != null) { + tw.writeAnnotValue(id, getterId, exprId) + } } } return id @@ -599,22 +609,26 @@ open class KotlinFileExtractor( // 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. - 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)) + 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 + 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) - } } + extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null) + } } + } } } // is IrErrorExpression @@ -900,9 +914,14 @@ open class KotlinFileExtractor( c.declarations .filterIsInstance() .map { - val getter = it.getter!! - val label = extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = true, extractAnnotations = true, null, listOf()) - tw.writeIsAnnotElem(label!!.cast()) + 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 = true, extractAnnotations = true, null, listOf())?.also { functionLabel -> + tw.writeIsAnnotElem(functionLabel.cast()) + } + } } } else { c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies, extractAnnotations = true) } From 5c019940dbc25966b1bc63312120a67fbc144f3c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 16:39:00 +0000 Subject: [PATCH 092/136] Fix missing !! removal --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 0783c7fdf1e..8cf78173b1d 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -489,7 +489,9 @@ open class KotlinFileExtractor( val containerClass = getOrCreateContainerClass(annotationClass) if (containerClass != null) - result.add(wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)) + wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)?.let { + result.add(it) + } else logger.warnElement("Failed to find an annotation container class", annotationClass) } From f9b878fe98a042899f57e61307371afc629dc6b8 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 16:39:21 +0000 Subject: [PATCH 093/136] Add test for .kt defined, Java used repeatable annotation --- .../kotlin/repeatable-annotations/JavaUser.java | 2 ++ .../kotlin/repeatable-annotations/test.expected | 7 ++++--- .../all-platforms/kotlin/repeatable-annotations/test.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) 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 index 959becd2682..610c373cb0f 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/JavaUser.java @@ -1,3 +1,5 @@ +@LocalRepeatable +@LocalRepeatable @LibRepeatable @LibRepeatable @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 index ff9e747cac5..7bda6ceff16 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected @@ -1,6 +1,7 @@ -| JavaUser.java:7:14:7:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} | -| JavaUser.java:7:14:7:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | JavaDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} | -| JavaUser.java:7:14:7:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | KtDefinedContainer | 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 | 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 | RetentionPolicy.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 | 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 index fa0700cea28..e0b7c69cb05 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.py @@ -4,4 +4,4 @@ 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(["javac JavaUser.java -cp out -d out2", "kotlinc test.kt -cp out -d out2"], lang="java") +run_codeql_database_create(["kotlinc test.kt -cp out -d out", "javac JavaUser.java -cp out -d out2"], lang="java") From 757fa60a468e13468e301bc70de2200fe8360ed6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 14 Nov 2022 16:40:23 +0000 Subject: [PATCH 094/136] Remove unused import --- java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt index 0bfed4a23c3..ab4010242a7 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource -import org.jetbrains.kotlin.name.ClassId // Adapted from Kotlin's interpreter/Utils.kt function 'internalName' // Translates class names into their JLS section 13.1 binary name, From 81353f865459aeb904b6170b2163316bd80e40dc Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 15 Nov 2022 18:20:03 +0000 Subject: [PATCH 095/136] Make annotation extraction compatible with all supported Kotlin versions --- .../src/main/kotlin/KotlinFileExtractor.kt | 103 +++++++++++++++--- .../utils/versions/v_1_4_32/annotationType.kt | 8 ++ .../kotlin/utils/versions/v_1_4_32/copyTo.kt | 7 ++ .../utils/versions/v_1_6_0/annotationType.kt | 6 + .../kotlin/utils/versions/v_1_7_20/copyTo.kt | 7 ++ 5 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/annotationType.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_4_32/copyTo.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_6_0/annotationType.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_7_20/copyTo.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 8cf78173b1d..25667221fd4 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2,18 +2,15 @@ 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.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.common.pop -import org.jetbrains.kotlin.backend.jvm.ir.getAnnotationRetention import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.config.JvmAnalysisFlags +import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget @@ -31,8 +28,32 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.ir.util.companionObject +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.hasInterfaceParent +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.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.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.JavaClass @@ -471,16 +492,24 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } + // 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 private fun groupRepeatableAnnotations(annotations: List): List { if (annotations.size < 2) return annotations - val annotationsByClass = annotations.groupByTo(mutableMapOf()) { it.symbol.owner.constructedClass } + 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.symbol.owner.constructedClass + val annotationClass = annotation.annotationClass val grouped = annotationsByClass.remove(annotationClass) ?: continue if (grouped.size < 2) { result.add(grouped.single()) @@ -501,7 +530,7 @@ open class KotlinFileExtractor( // Adapted from RepeatedAnnotationLowering.kt private fun getOrCreateContainerClass(annotationClass: IrClass): IrClass? { val metaAnnotations = annotationClass.annotations - val jvmRepeatable = metaAnnotations.find { it.isAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) } + 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 { @@ -701,8 +730,11 @@ open class KotlinFileExtractor( } } - // TODO: find out if we can spot when we're building for JVM <= 7 and omit the Java 8-only targets in that case. - private fun getAnnotationTargetMap() = jvm8TargetMap + 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? { @@ -751,6 +783,15 @@ open class KotlinFileExtractor( } } + // 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)) @@ -777,16 +818,46 @@ open class KotlinFileExtractor( private val javaAnnotationRepeatable by lazy { referenceExternalClass("java.lang.annotation.Repeatable") } private val kotlinAnnotationRepeatableContainer by lazy { 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!! + p.addGetter { + origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR + returnType = field.type + }.apply { + dispatchReceiverParameter = copyParameterToFunction(parentClass.thisReceiver!!, this) + 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, + dispatchReceiverParameter!!.type, + dispatchReceiverParameter!!.symbol + ) + ) + ) + ) + ) + } + } + // Taken from JvmCachedDeclarations.kt private fun getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass: IrClass) = globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(annotationClass) { val containerClass = pluginContext.irFactory.buildClass { kind = ClassKind.ANNOTATION_CLASS - name = Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME) + name = Name.identifier("Container") }.apply { createImplicitParameterDeclarationWithWrappedDescriptor() parent = annotationClass - superTypes = listOf(pluginContext.irBuiltIns.annotationType) + superTypes = listOf(getAnnotationType(pluginContext)) } val propertyName = Name.identifier("value") @@ -795,7 +866,7 @@ open class KotlinFileExtractor( containerClass.addConstructor { isPrimary = true }.apply { - addValueParameter(propertyName, propertyType) + addValueParameter(propertyName.identifier, propertyType) } containerClass.addProperty { @@ -808,7 +879,7 @@ open class KotlinFileExtractor( parent = containerClass correspondingPropertySymbol = this@property.symbol } - addDefaultGetter(containerClass, pluginContext.irBuiltIns) + addDefaultGetter(this, containerClass) } val repeatableContainerAnnotation = kotlinAnnotationRepeatableContainer?.let { it.constructors.single() } 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 From f9fc08bd4015531fbfeb4bfc21911991ddea1b67 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 15 Nov 2022 18:32:31 +0000 Subject: [PATCH 096/136] Replace uses of the !! operator in borrowed code --- .../src/main/kotlin/KotlinFileExtractor.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 25667221fd4..548a8436e0f 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -820,12 +820,16 @@ open class KotlinFileExtractor( // Taken from declarationBuilders.kt (not available in Kotlin < 1.6): private fun addDefaultGetter(p: IrProperty, parentClass: IrClass) { - val field = p.backingField!! + 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 { - dispatchReceiverParameter = copyParameterToFunction(parentClass.thisReceiver!!, this) + 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( @@ -838,8 +842,8 @@ open class KotlinFileExtractor( field.type, IrGetValueImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - dispatchReceiverParameter!!.type, - dispatchReceiverParameter!!.symbol + newParam.type, + newParam.symbol ) ) ) From 3dc9c2e57ba2912da7c688ee671ecad629a324fa Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 15 Nov 2022 18:36:03 +0000 Subject: [PATCH 097/136] Remove unnecessary unchecked cast --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 548a8436e0f..76483479d3d 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -4564,8 +4564,7 @@ open class KotlinFileExtractor( extractExpressionExpr(loop.condition, callable, id, 0, id) } - @Suppress("UNCHECKED_CAST") - private fun exprIdOrFresh(id: Label?) = id as? Label ?: tw.getFreshIdLabel() + private fun exprIdOrFresh(id: Label?) = id?.cast() ?: tw.getFreshIdLabel() private fun toUnbound(t: IrType) = when(t) { From c4ded5b4a7f855d54454270524dde4610d9756d7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 15 Nov 2022 18:37:57 +0000 Subject: [PATCH 098/136] Remove unused function --- .../kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 76483479d3d..089b4de5ee6 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -4566,12 +4566,6 @@ open class KotlinFileExtractor( private fun exprIdOrFresh(id: Label?) = id?.cast() ?: tw.getFreshIdLabel() - private fun toUnbound(t: IrType) = - when(t) { - is IrSimpleType -> t.classifier.typeWith() - else -> t - } - private fun extractClassReference( e: IrClassReference, parent: Label, From 80ef3a52908106534420dba493f824c9457f30dd Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 15 Nov 2022 19:08:02 +0000 Subject: [PATCH 099/136] Move meta-annotation support code out into its own class --- .../src/main/kotlin/KotlinFileExtractor.kt | 361 +--------------- .../src/main/kotlin/MetaAnnotationSupport.kt | 396 ++++++++++++++++++ 2 files changed, 400 insertions(+), 357 deletions(-) create mode 100644 java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 089b4de5ee6..f12a36c4310 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -7,18 +7,13 @@ import com.semmle.extractor.java.OdasaOutput import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.common.pop -import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.config.JvmAnalysisFlags -import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention -import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget 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.* @@ -29,14 +24,9 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.companionObject -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.hasInterfaceParent import org.jetbrains.kotlin.ir.util.isAnonymousObject import org.jetbrains.kotlin.ir.util.isFakeOverride @@ -54,7 +44,6 @@ 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.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaMethod @@ -62,12 +51,9 @@ import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name 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.lang.annotation.ElementType import java.util.* import kotlin.collections.ArrayList @@ -84,6 +70,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 @@ -492,80 +480,8 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - // 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 - private 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 - ) - ) - } - } - } - private fun extractAnnotations(annotations: List, parent: Label) { - val groupedAnnotations = groupRepeatableAnnotations(annotations) + val groupedAnnotations = metaAnnotationSupport.groupRepeatableAnnotations(annotations) for ((idx, constructorCall: IrConstructorCall) in groupedAnnotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { extractAnnotation(constructorCall, parent, idx) } @@ -678,275 +594,6 @@ open class KotlinFileExtractor( } } - private val javaAnnotationTargetElementType by lazy { referenceExternalClass("java.lang.annotation.ElementType") } - - private val javaAnnotationTarget by lazy { referenceExternalClass("java.lang.annotation.Target") } - - // 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 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 { referenceExternalClass("java.lang.annotation.Retention") } - private val javaAnnotationRetentionPolicy by lazy { 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 { referenceExternalClass("java.lang.annotation.Repeatable") } - private val kotlinAnnotationRepeatableContainer by lazy { 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) = - 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?.let { it.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): 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. - extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true) - - 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 { 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 - ) - } - - private fun generateJavaMetaAnnotations(c: IrClass) = - // This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend. - listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c), generateDocumentedAnnotation(c)) - fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label { with("class source", c) { DeclarationStackAdjuster(c).use { @@ -1035,7 +682,7 @@ open class KotlinFileExtractor( val additionalAnnotations = if (c.kind == ClassKind.ANNOTATION_CLASS && c.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) - generateJavaMetaAnnotations(c) + metaAnnotationSupport.generateJavaMetaAnnotations(c) else listOf() 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..e2713783382 --- /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): 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 = true) + + 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) = + // This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend. + listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c), generateDocumentedAnnotation(c)) +} + From 225913c49e15e3a9f2676e5b03cc99f095b0e0b6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 16 Nov 2022 11:28:05 +0000 Subject: [PATCH 100/136] Replace needless `map` call --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f12a36c4310..96053ac238b 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -637,7 +637,7 @@ open class KotlinFileExtractor( if (c.kind == ClassKind.ANNOTATION_CLASS) { c.declarations .filterIsInstance() - .map { + .forEach { val getter = it.getter if (getter == null) { logger.warnElement("Expected an annotation property to have a getter", it) From 0a788bcbc13e5926d5db59ce556c5a5c1d880fbb Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 21 Nov 2022 17:54:12 +0000 Subject: [PATCH 101/136] Don't extract return value type accesses for external annotations This would cause inconsistencies when both the source and external view of the class are in scope, since the type access has a fresh id. --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 96053ac238b..9314d2391b6 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -642,7 +642,7 @@ open class KotlinFileExtractor( if (getter == null) { logger.warnElement("Expected an annotation property to have a getter", it) } else { - extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = true, extractAnnotations = true, null, listOf())?.also { functionLabel -> + extractFunction(getter, id, extractBody = false, extractMethodAndParameterTypeAccesses = extractFunctionBodies, extractAnnotations = true, null, listOf())?.also { functionLabel -> tw.writeIsAnnotElem(functionLabel.cast()) } } From 5b2834c83321297e1a8b5c2b40961be617d018d7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 21 Nov 2022 18:52:49 +0000 Subject: [PATCH 102/136] Restrict type access extraction to classes extracted from source Type accesses have anonymous IDs, so we mimic the Java extractor and extract them only when seeing a class in a .kt source file. --- .../src/main/kotlin/KotlinFileExtractor.kt | 42 +++-- .../src/main/kotlin/MetaAnnotationSupport.kt | 8 +- .../PrintAst.expected | 171 +++++++++++++----- .../annotation-id-consistency/ktUser.kt | 7 + .../kotlin/annotation-id-consistency/test.kt | 14 +- .../kotlin/annotation-id-consistency/test.py | 2 +- 6 files changed, 170 insertions(+), 74 deletions(-) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 9314d2391b6..153032e5b68 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -208,7 +208,7 @@ open class KotlinFileExtractor( is IrField -> { val parentId = useDeclarationParent(getFieldParent(declaration), false)?.cast() if (parentId != null) { - extractField(declaration, parentId) + extractField(declaration, parentId, extractFunctionBodies) } Unit } @@ -480,21 +480,22 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - private fun extractAnnotations(annotations: List, parent: Label) { + private fun extractAnnotations(annotations: List, parent: Label, extractEnumTypeAccesses: Boolean) { val groupedAnnotations = metaAnnotationSupport.groupRepeatableAnnotations(annotations) for ((idx, constructorCall: IrConstructorCall) in groupedAnnotations.sortedBy { v -> v.type.classFqName?.asString() }.withIndex()) { - extractAnnotation(constructorCall, parent, idx) + extractAnnotation(constructorCall, parent, idx, extractEnumTypeAccesses) } } - private fun extractAnnotations(c: IrAnnotationContainer, parent: Label) { - extractAnnotations(c.annotations, parent) + private fun extractAnnotations(c: IrAnnotationContainer, parent: Label, extractEnumTypeAccesses: Boolean) { + extractAnnotations(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. @@ -518,7 +519,7 @@ open class KotlinFileExtractor( logger.warnElement("Expected annotation property to define a getter", prop) } else { val getterId = useFunction(getter) - val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType) + val exprId = extractAnnotationValueExpression(v, id, i, "{${getterId}}", getter.returnType, extractEnumTypeAccesses) if (exprId != null) { tw.writeAnnotValue(id, getterId, exprId) } @@ -532,7 +533,8 @@ open class KotlinFileExtractor( parent: Label, idx: Int, contextLabel: String, - contextType: IrType?): Label? { + contextType: IrType?, + extractEnumTypeAccesses: Boolean): Label? { fun exprId() = tw.getLabelFor("@\"annotationExpr;{$parent};$idx\"") @@ -541,7 +543,7 @@ open class KotlinFileExtractor( extractConstant(v, parent, idx, null, null, overrideId = exprId()) } is IrGetEnumValue -> { - extractEnumValue(v, parent, idx, null, null, overrideId = exprId()) + extractEnumValue(v, parent, idx, null, null, extractTypeAccess = extractEnumTypeAccesses, overrideId = exprId()) } is IrClassReference -> { val classRefId = exprId() @@ -549,7 +551,7 @@ open class KotlinFileExtractor( extractClassReference(v, parent, idx, null, null, overrideId = classRefId, typeAccessOverrideId = typeAccessId, useJavaLangClassType = true) } is IrConstructorCall -> { - extractAnnotation(v, parent, idx, contextLabel) + extractAnnotation(v, parent, idx, extractEnumTypeAccesses, contextLabel) } is IrVararg -> { tw.getLabelFor("@\"annotationarray;{${parent}};$contextLabel\"").also { arrayId -> @@ -573,7 +575,7 @@ open class KotlinFileExtractor( null } } - extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null) + extractAnnotationValueExpression(argExpr, arrayId, index, "child;$index", null, extractEnumTypeAccesses) } } } } @@ -682,11 +684,11 @@ open class KotlinFileExtractor( val additionalAnnotations = if (c.kind == ClassKind.ANNOTATION_CLASS && c.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) - metaAnnotationSupport.generateJavaMetaAnnotations(c) + metaAnnotationSupport.generateJavaMetaAnnotations(c, extractFunctionBodies) else listOf() - extractAnnotations(c.annotations + additionalAnnotations, id) + extractAnnotations(c.annotations + additionalAnnotations, id, extractFunctionBodies) if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) @@ -878,7 +880,7 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) - extractAnnotations(vp, id) + extractAnnotations(vp, id, extractTypeAccess) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -1419,7 +1421,7 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) if (extractAnnotations) - extractAnnotations(f, id) + extractAnnotations(f, id, extractMethodAndParameterTypeAccesses) return id } @@ -1432,13 +1434,13 @@ 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 val id = useField(f) - extractAnnotations(f, id) + 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)) } } @@ -1522,7 +1524,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) @@ -1578,7 +1580,7 @@ open class KotlinFileExtractor( extractDeclaration(it, extractPrivateMembers, extractFunctionBodies, extractAnnotations = true) } - extractAnnotations(ee, id) + extractAnnotations(ee, id, extractFunctionBodies) } } } @@ -4240,6 +4242,7 @@ open class KotlinFileExtractor( idx: Int, enclosingCallable: Label?, enclosingStmt: Label?, + extractTypeAccess: Boolean = true, overrideId: Label? = null ) = exprIdOrFresh(overrideId).also { id -> @@ -4254,7 +4257,8 @@ open class KotlinFileExtractor( val vId = useEnumEntry(owner) tw.writeVariableBinding(id, vId) - extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) + if (extractTypeAccess) + extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt) } } diff --git a/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt b/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt index e2713783382..5fdf073813d 100644 --- a/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt +++ b/java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt @@ -352,7 +352,7 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo } // Adapted from AdditionalClassAnnotationLowering.kt - private fun generateRepeatableAnnotation(irClass: IrClass): IrConstructorCall? { + private fun generateRepeatableAnnotation(irClass: IrClass, extractAnnotationTypeAccesses: Boolean): IrConstructorCall? { if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) || irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) ) return null @@ -361,7 +361,7 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo 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 = true) + extractor.extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = extractAnnotationTypeAccesses) val containerReference = IrClassReferenceImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType), @@ -389,8 +389,8 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo ) } - fun generateJavaMetaAnnotations(c: IrClass) = + fun generateJavaMetaAnnotations(c: IrClass, extractAnnotationTypeAccesses: Boolean) = // This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend. - listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c), generateDocumentedAnnotation(c)) + listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c, extractAnnotationTypeAccesses), generateDocumentedAnnotation(c)) } 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 index fa380ef7b00..dc889143ce4 100644 --- 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 @@ -18,58 +18,74 @@ User.java: # 4| 2: [ExprStmt] ; # 4| 0: [ClassInstanceExpr] new Annotated(...) # 4| -3: [TypeAccess] Annotated +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 test.kt: # 0| [CompilationUnit] test -# 3| 1: [Interface] Ann1 +# 4| 1: [Interface] Ann1 #-----| -3: (Annotations) # 0| 1: [Annotation] Retention # 0| 1: [VarAccess] RetentionPolicy.RUNTIME # 0| -1: [TypeAccess] RetentionPolicy -# 3| 1: [Method] x -# 3| 3: [TypeAccess] int -# 3| 2: [Method] y -# 3| 3: [TypeAccess] Ann2 -# 5| 2: [Interface] Ann2 +# 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 -# 5| 1: [Method] z -# 5| 3: [TypeAccess] String -# 5| 2: [Method] w -# 5| 3: [TypeAccess] Class -# 5| 0: [WildcardTypeAccess] ? ... -# 5| 3: [Method] v -# 5| 3: [TypeAccess] int[] -# 5| 4: [Method] u -# 5| 3: [TypeAccess] Ann3[] -# 5| 0: [TypeAccess] Ann3 -# 5| 5: [Method] t -# 5| 3: [TypeAccess] Class[] -# 5| 0: [TypeAccess] Class -# 5| 0: [WildcardTypeAccess] ? ... -# 7| 3: [Interface] Ann3 +# 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 -# 7| 1: [Method] a -# 7| 3: [TypeAccess] int -# 9| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation +# 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) -# 9| 0: [TypeVariable] T -# 9| 1: [Method] x -# 9| 3: [TypeAccess] Class -# 9| 0: [TypeAccess] T -# 9| 2: [Method] y -# 9| 3: [TypeAccess] Class[] -# 9| 0: [TypeAccess] Class -# 9| 0: [TypeAccess] T -# 11| 6: [Interface] VarargAnnotation +# 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 @@ -77,7 +93,7 @@ test.kt: # 0| 2: [Annotation] Retention # 0| 1: [VarAccess] RetentionPolicy.RUNTIME # 0| -1: [TypeAccess] RetentionPolicy -# 11| 3: [Annotation] Repeatable +# 12| 3: [Annotation] Repeatable # 0| 1: [Interface] Container #-----| -3: (Annotations) # 0| 1: [Annotation] RepeatableContainer @@ -87,32 +103,32 @@ test.kt: # 0| 1: [Method] value # 0| 3: [TypeAccess] VarargAnnotation[] # 0| 0: [TypeAccess] VarargAnnotation -# 12| 2: [Method] x -# 12| 3: [TypeAccess] int[] -# 14| 7: [Class] Annotated +# 13| 2: [Method] x +# 13| 3: [TypeAccess] int[] +# 15| 7: [Class] Annotated #-----| -3: (Annotations) # 0| 1: [Annotation] Container # 0| 1: [ArrayInit] {...} -# 16| 1: [Annotation] VarargAnnotation +# 17| 1: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} -# 17| 2: [Annotation] VarargAnnotation +# 18| 2: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 18| 3: [Annotation] VarargAnnotation +# 19| 3: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 -# 19| 4: [Annotation] VarargAnnotation +# 20| 4: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 20| 5: [Annotation] VarargAnnotation +# 21| 5: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 14| 2: [Annotation] Ann1 +# 15| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -132,11 +148,70 @@ test.kt: # 0| 0: [TypeAccess] String # 0| 1: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 15| 3: [Annotation] GenericAnnotation<> -# 21| 1: [Constructor] Annotated -# 14| 5: [BlockStmt] { ... } -# 14| 0: [SuperConstructorInvocationStmt] super(...) -# 21| 1: [BlockStmt] { ... } +# 0| 1: [VarAccess] DayOfWeek.MONDAY +# 0| -1: [TypeAccess] DayOfWeek +# 16| 3: [Annotation] GenericAnnotation<> +# 22| 1: [Constructor] Annotated +# 15| 5: [BlockStmt] { ... } +# 15| 0: [SuperConstructorInvocationStmt] super(...) +# 22| 1: [BlockStmt] { ... } +# 24| 8: [Class] AnnotatedUsedByKotlin +#-----| -3: (Annotations) +# 0| 1: [Annotation] Container +# 0| 1: [ArrayInit] {...} +# 26| 1: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 27| 2: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 28| 3: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 29| 4: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 30| 5: [Annotation] VarargAnnotation +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 24| 2: [Annotation] Ann1 +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [Annotation] Ann2 +# 0| 1: [StringLiteral] "Hello" +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [ArrayInit] {...} +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [IntegerLiteral] 3 +# 0| 1: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 2 +# 0| 1: [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [TypeLiteral] int.class +# 0| 0: [TypeAccess] int +# 0| 1: [VarAccess] DayOfWeek.MONDAY +# 0| -1: [TypeAccess] DayOfWeek +# 25| 3: [Annotation] GenericAnnotation<> +# 31| 1: [Constructor] AnnotatedUsedByKotlin +# 24| 5: [BlockStmt] { ... } +# 24| 0: [SuperConstructorInvocationStmt] super(...) +# 31| 1: [BlockStmt] { ... } +# 0| [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| [ArrayInit] {...} +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String +# 0| 1: [TypeLiteral] String.class +# 0| 0: [TypeAccess] String # 0| [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [ArrayInit] {...} 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..c7b2ce4fb56 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt @@ -0,0 +1,7 @@ +public class KtUser { + + fun user() { + val a = AnnotatedUsedByKotlin() + } + +} 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 index 50b87181a6f..304a9e006a0 100644 --- 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 @@ -1,6 +1,7 @@ import kotlin.reflect.KClass +import java.time.DayOfWeek -annotation class Ann1(val x: Int, val y: Ann2) { } +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>) { } @@ -11,7 +12,7 @@ annotation class GenericAnnotation(val x: KClass, val y: Array(String::class, arrayOf(String::class, String::class)) @VarargAnnotation @VarargAnnotation(1) @@ -20,3 +21,12 @@ annotation class VarargAnnotation(vararg val x: Int) { } @VarargAnnotation(*intArrayOf(1, 2, 3)) 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)) +class AnnotatedUsedByKotlin { } + 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 index 8ceac659f1d..49584531332 100644 --- 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 @@ -2,4 +2,4 @@ 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"], lang="java") +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") From 658c7a20cfb88572a4f2dde29ddbe6fd0f3d17b1 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 22 Nov 2022 15:11:36 +0000 Subject: [PATCH 103/136] Don't extract error expressions when a default value is missing This is a shortcoming of the Kotlin extractor, but at least this way we don't introduce an inconsistency if the annotation is later seen from .kt source or by the Java extractor --- .../src/main/kotlin/KotlinFileExtractor.kt | 14 +--- .../PrintAst.expected | 78 +++++++++++++------ .../kotlin/annotation-id-consistency/test.kt | 4 + 3 files changed, 61 insertions(+), 35 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 153032e5b68..bd58a446f9d 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -582,17 +582,9 @@ open class KotlinFileExtractor( } // is IrErrorExpression // null - else -> { - val eId = tw.getFreshIdLabel() - val type = useType(v?.type ?: pluginContext.irBuiltIns.unitType) - tw.writeExprs_errorexpr(eId, type.javaResult.id, parent, idx) - tw.writeExprsKotlinType(eId, type.kotlinResult.id) - - if (v != null) { - tw.writeHasLocation(eId, tw.getLocation(v)) - } - eId - } + // 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 } } 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 index dc889143ce4..646291dc565 100644 --- 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 @@ -105,30 +105,44 @@ test.kt: # 0| 0: [TypeAccess] VarargAnnotation # 13| 2: [Method] x # 13| 3: [TypeAccess] int[] -# 15| 7: [Class] Annotated +# 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] {...} -# 17| 1: [Annotation] VarargAnnotation +# 19| 1: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} -# 18| 2: [Annotation] VarargAnnotation +# 20| 2: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 19| 3: [Annotation] VarargAnnotation +# 21| 3: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 -# 20| 4: [Annotation] VarargAnnotation +# 22| 4: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 21| 5: [Annotation] VarargAnnotation +# 23| 5: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 15| 2: [Annotation] Ann1 +# 17| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -150,35 +164,43 @@ test.kt: # 0| 0: [TypeAccess] int # 0| 1: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek -# 16| 3: [Annotation] GenericAnnotation<> -# 22| 1: [Constructor] Annotated -# 15| 5: [BlockStmt] { ... } -# 15| 0: [SuperConstructorInvocationStmt] super(...) -# 22| 1: [BlockStmt] { ... } -# 24| 8: [Class] AnnotatedUsedByKotlin +# 18| 3: [Annotation] GenericAnnotation<> +# 24| 4: [Annotation] AnnWithDefaults +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [StringLiteral] "hello" +# 0| 1: [VarAccess] DayOfWeek.TUESDAY +# 0| -1: [TypeAccess] DayOfWeek +# 0| 1: [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] {...} -# 26| 1: [Annotation] VarargAnnotation +# 29| 1: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} -# 27| 2: [Annotation] VarargAnnotation +# 30| 2: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 28| 3: [Annotation] VarargAnnotation +# 31| 3: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 -# 29| 4: [Annotation] VarargAnnotation +# 32| 4: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 30| 5: [Annotation] VarargAnnotation +# 33| 5: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 # 0| 1: [IntegerLiteral] 2 # 0| 1: [IntegerLiteral] 3 -# 24| 2: [Annotation] Ann1 +# 27| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 # 0| 1: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" @@ -200,11 +222,19 @@ test.kt: # 0| 0: [TypeAccess] int # 0| 1: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek -# 25| 3: [Annotation] GenericAnnotation<> -# 31| 1: [Constructor] AnnotatedUsedByKotlin -# 24| 5: [BlockStmt] { ... } -# 24| 0: [SuperConstructorInvocationStmt] super(...) -# 31| 1: [BlockStmt] { ... } +# 28| 3: [Annotation] GenericAnnotation<> +# 34| 4: [Annotation] AnnWithDefaults +# 0| 1: [IntegerLiteral] 1 +# 0| 1: [StringLiteral] "hello" +# 0| 1: [VarAccess] DayOfWeek.TUESDAY +# 0| -1: [TypeAccess] DayOfWeek +# 0| 1: [ArrayInit] {...} +# 0| 1: [Annotation] Ann3 +# 0| 1: [IntegerLiteral] 1 +# 35| 1: [Constructor] AnnotatedUsedByKotlin +# 27| 5: [BlockStmt] { ... } +# 27| 0: [SuperConstructorInvocationStmt] super(...) +# 35| 1: [BlockStmt] { ... } # 0| [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [ArrayInit] {...} 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 index 304a9e006a0..de53d808df6 100644 --- 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 @@ -12,6 +12,8 @@ annotation class GenericAnnotation(val x: KClass, val y: 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 @@ -19,6 +21,7 @@ annotation class VarargAnnotation(vararg val x: Int) { } @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) @@ -28,5 +31,6 @@ class Annotated { } @VarargAnnotation(1, 2) @VarargAnnotation(*[1, 2, 3]) @VarargAnnotation(*intArrayOf(1, 2, 3)) +@AnnWithDefaults class AnnotatedUsedByKotlin { } From 8bbb34a498f7c93c7397cf58933f6815738ae35e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 22 Nov 2022 16:19:41 +0000 Subject: [PATCH 104/136] Convert kotlin.Deprecated back into a no-arg java.lang.Deprecated if applicable This at least maintains consistency with the Java extractor, although we lose its arguments if any were supplied Java-side. --- .../src/main/kotlin/KotlinFileExtractor.kt | 19 ++++++- .../PrintAst.expected | 50 +++++++++++++++++++ .../annotation-id-consistency/User.java | 2 +- .../deprecatedAnnotationTypes.expected | 5 ++ .../deprecatedAnnotationTypes.ql | 11 ++++ .../annotation-id-consistency/ktUser.kt | 4 ++ .../kotlin/annotation-id-consistency/test.kt | 11 ++++ 7 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.expected create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/deprecatedAnnotationTypes.ql diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index bd58a446f9d..452aa5b0c50 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -498,8 +498,19 @@ open class KotlinFileExtractor( extractEnumTypeAccesses: Boolean, contextLabel: String? = null ): Label { + val isConvertedJavaDeprecatedAnnotation = (constructorCall.type as? IrSimpleType)?.classFqName?.asString() == "kotlin.Deprecated" && + constructorCall.source is JavaSourceElement + + val extractType = + ( + if (isConvertedJavaDeprecatedAnnotation) + pluginContext.referenceClass(FqName("java.lang.Deprecated"))?.defaultType + else + null + ) ?: erase(constructorCall.type) + // 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 t = useType(extractType) val annotationContextLabel = contextLabel ?: "{${t.javaResult.id}}" val id = tw.getLabelFor("@\"annotation;{$parent};$annotationContextLabel\"") tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx) @@ -508,7 +519,11 @@ open class KotlinFileExtractor( val locId = tw.getLocation(constructorCall) tw.writeHasLocation(id, locId) - for (i in 0 until constructorCall.valueArgumentsCount) { + // If this is `java.lang.Deprecated`, extract an annotation without parameters -- whatever the original source + // may have supplied has been lost. + val paramCount = if (isConvertedJavaDeprecatedAnnotation) 0 else constructorCall.valueArgumentsCount + + for (i in 0 until paramCount) { val param = constructorCall.symbol.owner.valueParameters[i] val prop = constructorCall.symbol.owner.parentAsClass.declarations .filterIsInstance() 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 index 646291dc565..89fde9ad673 100644 --- 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 @@ -18,6 +18,12 @@ User.java: # 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 @@ -32,6 +38,20 @@ ktUser.kt: # 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 @@ -235,6 +255,36 @@ test.kt: # 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] { ... } # 0| [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [ArrayInit] {...} 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 index 7061beedb93..004e770ba96 100644 --- 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 @@ -1,7 +1,7 @@ public class User { public static void user(Ann1 a1, Ann2 a2) { - a1.x(); a2.z(); new Annotated(); + 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/ktUser.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ktUser.kt index c7b2ce4fb56..cb593ce11f1 100644 --- 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 @@ -2,6 +2,10 @@ 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/test.kt b/java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/test.kt index de53d808df6..44746342ae6 100644 --- 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 @@ -34,3 +34,14 @@ class Annotated { } @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 From 70ebb41d67541d109783d89441125a5e2352a97b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 24 Nov 2022 18:05:33 +0000 Subject: [PATCH 105/136] Restore nullability annotations This is imperfect since arguments to those annotations will be missing, but at least the common case of a plain `@NotNull` or `@Nullable` will be right, and the `@NotNull`s introduced by the Kotlin compiler will be present as expected. --- .../src/main/kotlin/KotlinFileExtractor.kt | 47 +++++++++++++++++-- .../AnnotatedMethods.java | 10 ++++ .../nullability-annotations/JavaUser.java | 7 +++ .../kotlin/nullability-annotations/ktUser.kt | 7 +++ .../org/jetbrains/annotations/NotNull.java | 6 +++ .../org/jetbrains/annotations/Nullable.java | 5 ++ .../nullability-annotations/test.expected | 12 +++++ .../kotlin/nullability-annotations/test.py | 6 +++ .../kotlin/nullability-annotations/test.ql | 11 +++++ .../nullability-annotations/zpkg/A.java | 3 ++ 10 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/NotNull.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/org/jetbrains/annotations/Nullable.java create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.ql create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/zpkg/A.java diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 452aa5b0c50..233cc588c95 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -14,6 +14,7 @@ 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.* @@ -44,8 +45,13 @@ 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 @@ -53,6 +59,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 @@ -887,7 +894,13 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(substitutedType, location, id, -1) } val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true) - extractAnnotations(vp, id, extractTypeAccess) + 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.annotations + extraAnnotations, id, extractTypeAccess) return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline) } } @@ -1337,6 +1350,32 @@ open class KotlinFileExtractor( logger.warn("Needed a signature for a type that doesn't have one") } + private fun getNullabilityAnnotationName(t: IrType, declOrigin: IrDeclarationOrigin, existingAnnotations: List, javaAnnotations: Collection?): FqName? { + if (t !is IrSimpleType) + return null + + 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 { existingAnnotations.any { existing -> existing.type.classFqName == it } } + } else { + // Kotlin declaration: add a NotNull annotation to a non-nullable non-primitive type. + JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.takeUnless { t.isNullable() || primitiveTypeMapping.getPrimitiveInfo(t) != null } + } + } + + 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 { @@ -1427,8 +1466,10 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) - if (extractAnnotations) - extractAnnotations(f, id, extractMethodAndParameterTypeAccesses) + if (extractAnnotations) { + val extraAnnotations = listOfNotNull(getNullabilityAnnotation(f.returnType, f.origin, f.annotations, getJavaCallable(f)?.annotations)) + extractAnnotations(f.annotations + extraAnnotations, id, extractMethodAndParameterTypeAccesses) + } return id } 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..fddcf0972b0 --- /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 { + + 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..a6f9b8b1053 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java @@ -0,0 +1,7 @@ +public class JavaUser { + + public static void test(KotlinAnnotatedMethods km) { + km.f(null); + } + +} 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..37c38850757 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt @@ -0,0 +1,7 @@ +import zpkg.A + +class KotlinAnnotatedMethods { + + @A fun f(@A m: AnnotatedMethods): String = m.notNullAnnotated("hello") + m.nullableAnnotated("world")!! + +} 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..0776438cca7 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected @@ -0,0 +1,12 @@ +| 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: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..02ba32b6675 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py @@ -0,0 +1,6 @@ +from create_database_utils import * + +os.mkdir('out') +os.mkdir('out2') +os.mkdir('out3') +run_codeql_database_create(["javac 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: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 { } From 8ca05d8fef3b56bcff3d42dbb6bb43c32c86ccec Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 25 Nov 2022 11:26:29 +0000 Subject: [PATCH 106/136] Exclude annotations from consistency check due to intentionally missing children --- java/ql/consistency-queries/children.ql | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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 From 01a534566003bc87d757d2cff31707eab5281cb9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 25 Nov 2022 17:53:58 +0000 Subject: [PATCH 107/136] Reimplement Deprecated annotation conversion suitable for older Kotlin versions --- .../src/main/kotlin/KotlinFileExtractor.kt | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 233cc588c95..d0609ec3ab7 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -487,15 +487,42 @@ open class KotlinFileExtractor( extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } - private fun extractAnnotations(annotations: List, parent: Label, extractEnumTypeAccesses: Boolean) { - val groupedAnnotations = metaAnnotationSupport.groupRepeatableAnnotations(annotations) + 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 as? IrSimpleType)?.classFqName?.asString() == "java.lang.Deprecated" } + 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 = when(c) { + is IrDeclaration -> c.origin + else -> null + } + 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.annotations, parent, extractEnumTypeAccesses) + extractAnnotations(c, c.annotations, parent, extractEnumTypeAccesses) } private fun extractAnnotation( @@ -505,19 +532,8 @@ open class KotlinFileExtractor( extractEnumTypeAccesses: Boolean, contextLabel: String? = null ): Label { - val isConvertedJavaDeprecatedAnnotation = (constructorCall.type as? IrSimpleType)?.classFqName?.asString() == "kotlin.Deprecated" && - constructorCall.source is JavaSourceElement - - val extractType = - ( - if (isConvertedJavaDeprecatedAnnotation) - pluginContext.referenceClass(FqName("java.lang.Deprecated"))?.defaultType - else - null - ) ?: erase(constructorCall.type) - // 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(extractType) + 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) @@ -526,11 +542,7 @@ open class KotlinFileExtractor( val locId = tw.getLocation(constructorCall) tw.writeHasLocation(id, locId) - // If this is `java.lang.Deprecated`, extract an annotation without parameters -- whatever the original source - // may have supplied has been lost. - val paramCount = if (isConvertedJavaDeprecatedAnnotation) 0 else constructorCall.valueArgumentsCount - - for (i in 0 until paramCount) { + for (i in 0 until constructorCall.valueArgumentsCount) { val param = constructorCall.symbol.owner.valueParameters[i] val prop = constructorCall.symbol.owner.parentAsClass.declarations .filterIsInstance() @@ -702,7 +714,7 @@ open class KotlinFileExtractor( else listOf() - extractAnnotations(c.annotations + additionalAnnotations, id, extractFunctionBodies) + extractAnnotations(c, c.annotations + additionalAnnotations, id, extractFunctionBodies) if (extractFunctionBodies && !c.isAnonymousObject && !c.isLocal) externalClassExtractor.writeStubTrapFile(c) @@ -900,7 +912,7 @@ open class KotlinFileExtractor( else -> null } val extraAnnotations = listOfNotNull(getNullabilityAnnotation(vp.type, vp.origin, vp.annotations, javaParameter?.annotations)) - extractAnnotations(vp.annotations + extraAnnotations, id, extractTypeAccess) + 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) } } @@ -1468,7 +1480,7 @@ open class KotlinFileExtractor( if (extractAnnotations) { val extraAnnotations = listOfNotNull(getNullabilityAnnotation(f.returnType, f.origin, f.annotations, getJavaCallable(f)?.annotations)) - extractAnnotations(f.annotations + extraAnnotations, id, extractMethodAndParameterTypeAccesses) + extractAnnotations(f, f.annotations + extraAnnotations, id, extractMethodAndParameterTypeAccesses) } return id From f6888c727f1ab3f8473cd5d5674713f0fbdcf423 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Nov 2022 12:57:16 +0000 Subject: [PATCH 108/136] PrintAst: Assign indices to annotation children that don't have source locations This avoids them all tying at rank 1 as before. --- .../PrintAst.expected | 76 +++++++++---------- java/ql/lib/semmle/code/java/PrintAst.qll | 18 +++-- .../annotation_classes/PrintAst.expected | 58 +++++++------- 3 files changed, 77 insertions(+), 75 deletions(-) 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 index 89fde9ad673..5710e0a8ef1 100644 --- 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 @@ -151,46 +151,46 @@ test.kt: # 21| 3: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 +# 0| 2: [IntegerLiteral] 2 # 22| 4: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 # 23| 5: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 # 17| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 -# 0| 1: [Annotation] Ann2 +# 0| 2: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" -# 0| 1: [TypeLiteral] String.class +# 0| 2: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [ArrayInit] {...} +# 0| 3: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 -# 0| 1: [ArrayInit] {...} +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 0| 4: [ArrayInit] {...} # 0| 1: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 1 -# 0| 1: [Annotation] Ann3 +# 0| 2: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 2 -# 0| 1: [ArrayInit] {...} +# 0| 5: [ArrayInit] {...} # 0| 1: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [TypeLiteral] int.class +# 0| 2: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 0| 1: [VarAccess] DayOfWeek.MONDAY +# 0| 3: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek # 18| 3: [Annotation] GenericAnnotation<> # 24| 4: [Annotation] AnnWithDefaults # 0| 1: [IntegerLiteral] 1 -# 0| 1: [StringLiteral] "hello" -# 0| 1: [VarAccess] DayOfWeek.TUESDAY +# 0| 2: [StringLiteral] "hello" +# 0| 3: [VarAccess] DayOfWeek.TUESDAY # 0| -1: [TypeAccess] DayOfWeek -# 0| 1: [ArrayInit] {...} +# 0| 4: [ArrayInit] {...} # 0| 1: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 1 # 25| 1: [Constructor] Annotated @@ -209,46 +209,46 @@ test.kt: # 31| 3: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 +# 0| 2: [IntegerLiteral] 2 # 32| 4: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 # 33| 5: [Annotation] VarargAnnotation # 0| 1: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 # 27| 2: [Annotation] Ann1 # 0| 1: [IntegerLiteral] 1 -# 0| 1: [Annotation] Ann2 +# 0| 2: [Annotation] Ann2 # 0| 1: [StringLiteral] "Hello" -# 0| 1: [TypeLiteral] String.class +# 0| 2: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [ArrayInit] {...} +# 0| 3: [ArrayInit] {...} # 0| 1: [IntegerLiteral] 1 -# 0| 1: [IntegerLiteral] 2 -# 0| 1: [IntegerLiteral] 3 -# 0| 1: [ArrayInit] {...} +# 0| 2: [IntegerLiteral] 2 +# 0| 3: [IntegerLiteral] 3 +# 0| 4: [ArrayInit] {...} # 0| 1: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 1 -# 0| 1: [Annotation] Ann3 +# 0| 2: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 2 -# 0| 1: [ArrayInit] {...} +# 0| 5: [ArrayInit] {...} # 0| 1: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [TypeLiteral] int.class +# 0| 2: [TypeLiteral] int.class # 0| 0: [TypeAccess] int -# 0| 1: [VarAccess] DayOfWeek.MONDAY +# 0| 3: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek # 28| 3: [Annotation] GenericAnnotation<> # 34| 4: [Annotation] AnnWithDefaults # 0| 1: [IntegerLiteral] 1 -# 0| 1: [StringLiteral] "hello" -# 0| 1: [VarAccess] DayOfWeek.TUESDAY +# 0| 2: [StringLiteral] "hello" +# 0| 3: [VarAccess] DayOfWeek.TUESDAY # 0| -1: [TypeAccess] DayOfWeek -# 0| 1: [ArrayInit] {...} +# 0| 4: [ArrayInit] {...} # 0| 1: [Annotation] Ann3 # 0| 1: [IntegerLiteral] 1 # 35| 1: [Constructor] AnnotatedUsedByKotlin @@ -290,12 +290,12 @@ test.kt: # 0| [ArrayInit] {...} # 0| 1: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [TypeLiteral] String.class +# 0| 2: [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [TypeLiteral] String.class # 0| 0: [TypeAccess] String # 0| [ArrayInit] {...} # 0| 1: [TypeLiteral] String.class # 0| 0: [TypeAccess] String -# 0| 1: [TypeLiteral] String.class +# 0| 2: [TypeLiteral] String.class # 0| 0: [TypeAccess] String diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 802ba19030b..0e52be33149 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -298,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) } } diff --git a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected index 79bc39c4392..c457b0811dd 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/annotation_classes/PrintAst.expected @@ -41,8 +41,8 @@ def.kt: # 47| -1: [TypeAccess] ConsoleKt # 47| 0: [MethodAccess] a(...) # 47| -1: [VarAccess] a -# 49| 1: [LocalVariableDeclStmt] var ...; -# 49| 1: [LocalVariableDeclExpr] x +# 50| 1: [LocalVariableDeclStmt] var ...; +# 50| 1: [LocalVariableDeclExpr] x # 50| 0: [IntegerLiteral] 10 # 53| 3: [FieldDeclaration] int p; #-----| -2: (Annotations) @@ -91,51 +91,51 @@ def.kt: # 0| 1: [ArrayInit] {...} # 0| 1: [VarAccess] ElementType.TYPE # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.FIELD +# 0| 2: [VarAccess] ElementType.FIELD # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.METHOD +# 0| 3: [VarAccess] ElementType.METHOD # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.PARAMETER +# 0| 4: [VarAccess] ElementType.PARAMETER # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.CONSTRUCTOR +# 0| 5: [VarAccess] ElementType.CONSTRUCTOR # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.LOCAL_VARIABLE +# 0| 6: [VarAccess] ElementType.LOCAL_VARIABLE # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.ANNOTATION_TYPE +# 0| 7: [VarAccess] ElementType.ANNOTATION_TYPE # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.TYPE_PARAMETER +# 0| 8: [VarAccess] ElementType.TYPE_PARAMETER # 0| -1: [TypeAccess] ElementType -# 0| 1: [VarAccess] ElementType.TYPE_USE +# 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| 1: [VarAccess] AnnotationTarget.ANNOTATION_CLASS +# 0| 2: [VarAccess] AnnotationTarget.ANNOTATION_CLASS # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.TYPE_PARAMETER +# 0| 3: [VarAccess] AnnotationTarget.TYPE_PARAMETER # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.PROPERTY +# 0| 4: [VarAccess] AnnotationTarget.PROPERTY # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.FIELD +# 0| 5: [VarAccess] AnnotationTarget.FIELD # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.LOCAL_VARIABLE +# 0| 6: [VarAccess] AnnotationTarget.LOCAL_VARIABLE # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.VALUE_PARAMETER +# 0| 7: [VarAccess] AnnotationTarget.VALUE_PARAMETER # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.CONSTRUCTOR +# 0| 8: [VarAccess] AnnotationTarget.CONSTRUCTOR # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.FUNCTION +# 0| 9: [VarAccess] AnnotationTarget.FUNCTION # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.PROPERTY_GETTER +# 0| 10: [VarAccess] AnnotationTarget.PROPERTY_GETTER # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.PROPERTY_SETTER +# 0| 11: [VarAccess] AnnotationTarget.PROPERTY_SETTER # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.TYPE +# 0| 12: [VarAccess] AnnotationTarget.TYPE # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.FILE +# 0| 13: [VarAccess] AnnotationTarget.FILE # 0| -1: [TypeAccess] AnnotationTarget -# 0| 1: [VarAccess] AnnotationTarget.TYPEALIAS +# 0| 14: [VarAccess] AnnotationTarget.TYPEALIAS # 0| -1: [TypeAccess] AnnotationTarget # 21| 1: [Method] a #-----| 1: (Annotations) @@ -204,17 +204,17 @@ def.kt: # 0| 1: [IntegerLiteral] 1 # 39| 2: [Annotation] Annot1k # 0| 1: [IntegerLiteral] 2 -# 0| 1: [StringLiteral] "ab" -# 0| 1: [TypeLiteral] X.class +# 0| 2: [StringLiteral] "ab" +# 0| 3: [TypeLiteral] X.class # 0| 0: [TypeAccess] X -# 0| 1: [VarAccess] Y.B +# 0| 4: [VarAccess] Y.B # 0| -1: [TypeAccess] Y -# 0| 1: [ArrayInit] {...} +# 0| 5: [ArrayInit] {...} # 0| 1: [VarAccess] Y.C # 0| -1: [TypeAccess] Y -# 0| 1: [VarAccess] Y.A +# 0| 2: [VarAccess] Y.A # 0| -1: [TypeAccess] Y -# 0| 1: [Annotation] Annot0k +# 0| 6: [Annotation] Annot0k # 0| 1: [IntegerLiteral] 1 # 42| 1: [Constructor] Z #-----| 1: (Annotations) From 7a7c08b185f0005f31bcad6a1d392b92ab07b072 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 30 Nov 2022 13:01:52 +0000 Subject: [PATCH 109/136] Tolerate generic annotations This causes them to render properly in PrintAst output due to `getAnnotationElement` working as expected, and will hide the fact that they are represented by raw types in bytecode. --- .../PrintAst.expected | 32 +++++++++---------- java/ql/lib/semmle/code/java/Annotation.qll | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) 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 index 5710e0a8ef1..751777f3748 100644 --- 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 @@ -184,7 +184,14 @@ test.kt: # 0| 0: [TypeAccess] int # 0| 3: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek -# 18| 3: [Annotation] GenericAnnotation<> +# 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" @@ -242,7 +249,14 @@ test.kt: # 0| 0: [TypeAccess] int # 0| 3: [VarAccess] DayOfWeek.MONDAY # 0| -1: [TypeAccess] DayOfWeek -# 28| 3: [Annotation] GenericAnnotation<> +# 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" @@ -285,17 +299,3 @@ test.kt: # 46| 5: [BlockStmt] { ... } # 46| 0: [SuperConstructorInvocationStmt] super(...) # 47| 1: [BlockStmt] { ... } -# 0| [TypeLiteral] String.class -# 0| 0: [TypeAccess] String -# 0| [ArrayInit] {...} -# 0| 1: [TypeLiteral] String.class -# 0| 0: [TypeAccess] String -# 0| 2: [TypeLiteral] String.class -# 0| 0: [TypeAccess] String -# 0| [TypeLiteral] String.class -# 0| 0: [TypeAccess] String -# 0| [ArrayInit] {...} -# 0| 1: [TypeLiteral] String.class -# 0| 0: [TypeAccess] String -# 0| 2: [TypeLiteral] String.class -# 0| 0: [TypeAccess] String diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index dd6762776c6..7e495c4ee2d 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -37,7 +37,7 @@ 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().(AnnotationType).getSourceDeclaration() } /** Gets the annotation element with the specified `name`. */ AnnotationElement getAnnotationElement(string name) { From c8e2ae8563af0923e905f80be5843fe27ac274d9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 30 Nov 2022 16:29:47 +0000 Subject: [PATCH 110/136] Accept integration test changes These introduce newly-extracted annotations, and note that enum constants no longer get type-access expressions in some circumstances --- .../PrintAst.expected | 110 ++++++++++++++++++ .../repeatable-annotations/test.expected | 6 +- 2 files changed, 113 insertions(+), 3 deletions(-) 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..9ca1980904d 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,18 @@ 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 +# 0| 2: [Annotation] NotNull #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -41,6 +52,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 +66,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 +193,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 +209,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 +241,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 +264,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 +406,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 +417,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 ...; @@ -398,6 +445,8 @@ app/src/main/kotlin/testProject/App.kt: # 7| -1: [VarAccess] tmp1_output # 7| 0: [VarAccess] tmp0_desc # 7| 6: [Constructor] $serializer +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } @@ -436,18 +485,26 @@ 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] { ... } # 7| 0: [ReturnStmt] return ... # 7| 0: [VarAccess] INSTANCE # 7| 2: [Constructor] Companion +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } # 8| 12: [Constructor] Project +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull #-----| 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 +521,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 +539,22 @@ 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 +# 0| 2: [Annotation] NotNull #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -530,13 +602,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 +645,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 +668,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 +774,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 +785,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 ...; @@ -713,6 +813,8 @@ app/src/main/kotlin/testProject/App.kt: # 14| -1: [VarAccess] tmp1_output # 14| 0: [VarAccess] tmp0_desc # 14| 6: [Constructor] $serializer +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 14| 1: [BlockStmt] { ... } @@ -746,16 +848,22 @@ 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] { ... } # 14| 0: [ReturnStmt] return ... # 14| 0: [VarAccess] INSTANCE # 14| 2: [Constructor] Companion +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 14| 1: [BlockStmt] { ... } # 15| 5: [Constructor] X +#-----| 1: (Annotations) +# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 15| 1: [BlockStmt] { ... } @@ -766,6 +874,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/repeatable-annotations/test.expected b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected index 7bda6ceff16..6ae3379e99f 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected +++ b/java/ql/integration-tests/all-platforms/kotlin/repeatable-annotations/test.expected @@ -3,11 +3,11 @@ | 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 | RetentionPolicy.RUNTIME | +| 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 | RetentionPolicy.RUNTIME | +| 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 | RetentionPolicy.RUNTIME | +| 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 | {...} | From f5dc5155f93209156643f1f770e83e70ccbf1c32 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 30 Nov 2022 17:40:41 +0000 Subject: [PATCH 111/136] Don't introduce @NotNull on Kotlin methods that already have that annotation This usually can't happen, but delegates pointing at Java appear to be synthesised with this normally-hidden annotation --- .../src/main/kotlin/KotlinFileExtractor.kt | 11 ++++++++--- .../AnnotatedInterface.java | 10 ++++++++++ .../AnnotatedMethods.java | 2 +- .../kotlin/nullability-annotations/JavaUser.java | 3 ++- .../kotlin/nullability-annotations/ktUser.kt | 2 ++ .../kotlin/nullability-annotations/test.expected | 16 ++++++++++++++++ .../kotlin/nullability-annotations/test.py | 2 +- 7 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedInterface.java diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index d0609ec3ab7..1840014e435 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1366,14 +1366,19 @@ open class KotlinFileExtractor( 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 { existingAnnotations.any { existing -> existing.type.classFqName == it } } + ?.takeUnless { hasExistingAnnotation(it) } } else { - // Kotlin declaration: add a NotNull annotation to a non-nullable non-primitive type. - JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.takeUnless { t.isNullable() || primitiveTypeMapping.getPrimitiveInfo(t) != null } + // 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) } } } 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 index fddcf0972b0..16671f5468f 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/AnnotatedMethods.java @@ -1,7 +1,7 @@ import org.jetbrains.annotations.*; import zpkg.A; -public class AnnotatedMethods { +public class AnnotatedMethods implements AnnotatedInterface { public @A @NotNull String notNullAnnotated(@A @NotNull 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 index a6f9b8b1053..6031901c3a3 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/JavaUser.java @@ -1,7 +1,8 @@ public class JavaUser { - public static void test(KotlinAnnotatedMethods km) { + 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 index 37c38850757..06c1d580503 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/ktUser.kt @@ -5,3 +5,5 @@ 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/test.expected b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected index 0776438cca7..89eb06d26c3 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.expected @@ -1,3 +1,11 @@ +| 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 | @@ -6,6 +14,14 @@ | 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 | 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 index 02ba32b6675..4072b3d454e 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py @@ -3,4 +3,4 @@ from create_database_utils import * os.mkdir('out') os.mkdir('out2') os.mkdir('out3') -run_codeql_database_create(["javac 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:out2 -d out3"], lang="java") +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:out2 -d out3"], lang="java") From 78234c52fd9b694b8bafff38e347310a61700ddb Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 1 Dec 2022 10:13:56 +0000 Subject: [PATCH 112/136] Ensure constructors don't get nullability annotations --- .../kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 1840014e435..f223a8f66e1 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1484,7 +1484,11 @@ open class KotlinFileExtractor( linesOfCode?.linesOfCodeInDeclaration(f, id) if (extractAnnotations) { - val extraAnnotations = listOfNotNull(getNullabilityAnnotation(f.returnType, f.origin, f.annotations, getJavaCallable(f)?.annotations)) + 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) } From 251513c1d37fbf6ce155420c401c894c6ae439b5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 1 Dec 2022 10:33:59 +0000 Subject: [PATCH 113/136] Format ql --- java/ql/lib/semmle/code/java/Annotation.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 7e495c4ee2d..e61f4693aac 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().(AnnotationType).getSourceDeclaration() } + override AnnotationType getType() { + result = Expr.super.getType().(AnnotationType).getSourceDeclaration() + } /** Gets the annotation element with the specified `name`. */ AnnotationElement getAnnotationElement(string name) { From 93ea433c49407e1a37ef4e8633cfdbfa180a1e7e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 7 Dec 2022 18:35:57 +0000 Subject: [PATCH 114/136] Add missing imports --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f223a8f66e1..252bd97fa33 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -29,12 +29,14 @@ 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 From a161d79cd84e9dd86c73c4be4e02dda6582b5aaf Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 7 Dec 2022 18:48:01 +0000 Subject: [PATCH 115/136] Remove no-longer-needed expected diagnostics --- java/ql/test/kotlin/library-tests/annotation_classes/def.kt | 3 --- 1 file changed, 3 deletions(-) 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 2fb107c1263..f499d1026fc 100644 --- a/java/ql/test/kotlin/library-tests/annotation_classes/def.kt +++ b/java/ql/test/kotlin/library-tests/annotation_classes/def.kt @@ -60,6 +60,3 @@ fun @receiver:Annot0k String.myExtension() { } @Annot0k typealias AAA = Z - -// Diagnostic Matches: Incomplete annotation: @kotlin.annotation.Target(%) -// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(%) From 65dc0dc326fd04e9684d69ff7c8fb6bba14e5ea8 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 9 Dec 2022 11:17:37 +0000 Subject: [PATCH 116/136] Add dummy extensible predicate definition to integration test --- .../kotlin/annotation-id-consistency/ext/test.model.yml | 5 +++++ .../kotlin/annotation-id-consistency/qlpack.yml | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/ext/test.model.yml create mode 100644 java/ql/integration-tests/all-platforms/kotlin/annotation-id-consistency/qlpack.yml 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/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 + From 40e902eca948d70f3536bea7a1654e34ebd3135d Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 9 Dec 2022 11:52:28 +0000 Subject: [PATCH 117/136] Look through generic annotation types extracted from Kotlin --- java/ql/lib/semmle/code/java/Annotation.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index e61f4693aac..fa010ec88c0 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -38,7 +38,7 @@ class Annotation extends @annotation, Expr { /** Gets the annotation type declaration for this annotation. */ override AnnotationType getType() { - result = Expr.super.getType().(AnnotationType).getSourceDeclaration() + result = Expr.super.getType().(Interface).getSourceDeclaration() } /** Gets the annotation element with the specified `name`. */ From b8ed3b7dbf93ed54d7619c5b40a46aa0bb8b0d87 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 9 Dec 2022 12:57:20 +0000 Subject: [PATCH 118/136] Accept annotation test changes These are notnull annotations that no longer get inappropriately attached to constructors --- .../gradle_kotlinx_serialization/PrintAst.expected | 14 -------------- 1 file changed, 14 deletions(-) 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 9ca1980904d..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 @@ -12,7 +12,6 @@ app/src/main/kotlin/testProject/App.kt: # 0| 2: [ArrayInit] {...} # 0| 3: [VarAccess] DeprecationLevel.HIDDEN # 0| -1: [TypeAccess] DeprecationLevel -# 0| 2: [Annotation] NotNull #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -445,8 +444,6 @@ app/src/main/kotlin/testProject/App.kt: # 7| -1: [VarAccess] tmp1_output # 7| 0: [VarAccess] tmp0_desc # 7| 6: [Constructor] $serializer -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } @@ -493,14 +490,10 @@ app/src/main/kotlin/testProject/App.kt: # 7| 0: [ReturnStmt] return ... # 7| 0: [VarAccess] INSTANCE # 7| 2: [Constructor] Companion -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } # 8| 12: [Constructor] Project -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull #-----| 4: (Parameters) # 8| 0: [Parameter] name #-----| -1: (Annotations) @@ -554,7 +547,6 @@ app/src/main/kotlin/testProject/App.kt: # 0| 2: [ArrayInit] {...} # 0| 3: [VarAccess] DeprecationLevel.HIDDEN # 0| -1: [TypeAccess] DeprecationLevel -# 0| 2: [Annotation] NotNull #-----| 4: (Parameters) # 0| 0: [Parameter] seen1 # 0| 0: [TypeAccess] int @@ -813,8 +805,6 @@ app/src/main/kotlin/testProject/App.kt: # 14| -1: [VarAccess] tmp1_output # 14| 0: [VarAccess] tmp0_desc # 14| 6: [Constructor] $serializer -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 14| 1: [BlockStmt] { ... } @@ -856,14 +846,10 @@ app/src/main/kotlin/testProject/App.kt: # 14| 0: [ReturnStmt] return ... # 14| 0: [VarAccess] INSTANCE # 14| 2: [Constructor] Companion -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 14| 1: [BlockStmt] { ... } # 15| 5: [Constructor] X -#-----| 1: (Annotations) -# 0| 1: [Annotation] NotNull # 14| 5: [BlockStmt] { ... } # 14| 0: [SuperConstructorInvocationStmt] super(...) # 15| 1: [BlockStmt] { ... } From ad90e58120348c4d681cc7efadbf97666f0eda7e Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 15:20:49 +0100 Subject: [PATCH 119/136] C#: Rename Negative Summary Model to Neutral Model. --- .../ext/generated/dotnet_runtime.model.yml | 2 +- .../code/csharp/dataflow/ExternalFlow.qll | 42 +++++++++---------- .../dataflow/internal/DataFlowPrivate.qll | 4 +- .../dataflow/internal/FlowSummaryImpl.qll | 28 ++++++------- .../internal/FlowSummaryImplSpecific.qll | 8 ++-- .../ql/src/Telemetry/SupportedExternalApis.ql | 2 +- .../src/Telemetry/UnsupportedExternalAPIs.ql | 2 +- .../frameworks/UnsupportedExternalAPIs.ql | 2 +- .../CaptureNegativeSummaryModels.ql | 6 +-- .../ExtractNegativeSummaries.ql | 8 ++-- .../modelgenerator/internal/CaptureModels.qll | 4 +- .../internal/CaptureModelsSpecific.qll | 2 +- .../internal/CaptureSummaryFlow.qll | 6 +-- .../dataflow/library/FlowSummaries.expected | 2 +- .../dataflow/library/FlowSummaries.ql | 8 ++-- .../library/FlowSummariesFiltered.expected | 2 +- .../EntityFramework/FlowSummaries.expected | 2 +- 17 files changed, 62 insertions(+), 68 deletions(-) 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..e6e98a9d222 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. @@ -133,16 +133,16 @@ private class SummaryModelCsvInternal extends Unit { } /** - * DEPRECATED: Define negative summary models as data extensions instead. + * DEPRECATED: Define neutral models as data extensions instead. * - * A unit class for adding additional negative summary model rows. + * A unit class for adding additional neutral model rows. * - * Extend this class to add additional negative summary definitions. + * Extend this class to add additional neutral definitions. */ -deprecated class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal; +deprecated class NeutralModelCsv = NeutralModelCsvInternal; -private class NegativeSummaryModelCsvInternal extends Unit { - /** Holds if `row` specifies a negative summary definition. */ +private class NeutralModelCsvInternal extends Unit { + /** Holds if `row` specifies a neutral definition. */ abstract predicate row(string row); } @@ -152,9 +152,7 @@ private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -private predicate negativeSummaryModelInternal(string row) { - any(NegativeSummaryModelCsvInternal s).row(row) -} +private predicate neutralModelInternal(string row) { any(NeutralModelCsvInternal s).row(row) } /** * Holds if a source model exists for the given parameters. @@ -243,17 +241,17 @@ 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 + neutralModelInternal(row) and row.splitAt(";", 0) = namespace and row.splitAt(";", 1) = type and row.splitAt(";", 2) = name and @@ -261,7 +259,7 @@ predicate negativeSummaryModel( row.splitAt(";", 4) = provenance ) or - extNegativeSummaryModel(namespace, type, name, signature, provenance) + extNeutralModel(namespace, type, name, signature, provenance) } private predicate relevantNamespace(string namespace) { @@ -394,7 +392,7 @@ module ModelValidation { or summaryModelInternal(row) and expect = 10 and pred = "summary" or - negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary" + neutralModelInternal(row) and expect = 5 and pred = "neutral" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and @@ -418,9 +416,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 +459,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 +593,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/CaptureNegativeSummaryModels.ql index 9188b54ef40..9cf2b81ba7c 100644 --- a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.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/ExtractNegativeSummaries.ql index 53681f5f684..5ca6ef9579c 100644 --- a/csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql +++ b/csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.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 | From 079d48c42a4ead174bdc8fc27a16e3a0c0da54f9 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 15:21:04 +0100 Subject: [PATCH 120/136] Sync files. --- .../go/dataflow/internal/FlowSummaryImpl.qll | 28 +++++++++---------- .../dataflow/internal/FlowSummaryImpl.qll | 28 +++++++++---------- .../modelgenerator/internal/CaptureModels.qll | 4 +-- .../dataflow/new/internal/FlowSummaryImpl.qll | 28 +++++++++---------- .../dataflow/internal/FlowSummaryImpl.qll | 28 +++++++++---------- .../dataflow/internal/FlowSummaryImpl.qll | 28 +++++++++---------- 6 files changed, 71 insertions(+), 73 deletions(-) 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/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/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/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/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/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 ) } } From 3af00a8f3fb791547feeb927258c797017034cdd Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:33:12 +0100 Subject: [PATCH 121/136] Java: Rename Negative Summary Model to Neutral Model. --- java/ql/lib/ext/dummy.model.yml | 2 +- .../lib/ext/generated/kotlinstdlib.model.yml | 2 +- .../generated/org.apache.commons.io.model.yml | 2 +- .../code/java/dataflow/ExternalFlow.qll | 44 +++++++++---------- .../internal/FlowSummaryImplSpecific.qll | 8 ++-- .../ql/src/Telemetry/SupportedExternalApis.ql | 2 +- .../src/Telemetry/UnsupportedExternalAPIs.ql | 2 +- .../CaptureNegativeSummaryModels.ql | 6 +-- .../ExtractNegativeSummaries.ql | 8 ++-- .../internal/CaptureModelsSpecific.qll | 4 +- .../internal/CaptureSummaryFlow.qll | 6 +-- 11 files changed, 41 insertions(+), 45 deletions(-) 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/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 14773872ba0..f3465cad3f9 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. @@ -123,16 +123,16 @@ private class SummaryModelCsvInternal extends Unit { } /** - * DEPRECATED: Define negative summary models as data extensions instead. + * DEPRECATED: Define neutral models as data extensions instead. * - * A unit class for adding additional negative summary model rows. + * A unit class for adding additional neutral model rows. * - * Extend this class to add additional negative summary definitions. + * Extend this class to add additional neutral definitions. */ -deprecated class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal; +deprecated class NeutralModelCsv = NeutralModelCsvInternal; -private class NegativeSummaryModelCsvInternal extends Unit { - /** Holds if `row` specifies a negative summary definition. */ +private class NeutralModelCsvInternal extends Unit { + /** Holds if `row` specifies a neutral definition. */ abstract predicate row(string row); } @@ -142,9 +142,7 @@ private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) } -private predicate negativeSummaryModelInternal(string row) { - any(NegativeSummaryModelCsvInternal s).row(row) -} +private predicate neutralModelInternal(string row) { any(NeutralModelCsvInternal s).row(row) } /** * Holds if an experimental source model exists for the given parameters. @@ -313,17 +311,15 @@ 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 -) { +/** 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) { exists(string row | - negativeSummaryModelInternal(row) and + neutralModelInternal(row) and row.splitAt(";", 0) = package and row.splitAt(";", 1) = type and row.splitAt(";", 2) = name and @@ -331,7 +327,7 @@ predicate negativeSummaryModel( row.splitAt(";", 4) = provenance ) or - extNegativeSummaryModel(package, type, name, signature, provenance) + extNeutralModel(package, type, name, signature, provenance) } private predicate relevantPackage(string package) { @@ -473,7 +469,7 @@ module ModelValidation { or summaryModelInternal(row) and expect = 10 and pred = "summary" or - negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary" + neutralModelInternal(row) and expect = 5 and pred = "neutral" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and @@ -497,9 +493,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 +537,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 +586,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/FlowSummaryImplSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll index c3366436d27..179bc0ab38c 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll @@ -160,12 +160,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/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/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql index a6f6e5f26e5..96744de89b6 100644 --- a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.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/modelconverter/ExtractNegativeSummaries.ql b/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql index e762b3ee6e5..ad7cef84f04 100644 --- a/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql +++ b/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.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/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) } From f4f7d83349dfa10c0ffa6af34ef3b2b14dd4dcc6 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:36:11 +0100 Subject: [PATCH 122/136] Python: Rename Negative Summary Model to Neutral Model. --- .../dataflow/new/internal/FlowSummaryImplSpecific.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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. From a14df1ca618066978c17793236fc7e57a0bdc826 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:38:01 +0100 Subject: [PATCH 123/136] Ruby: Rename Negative Summary Model to Neutral Model. --- .../ruby/dataflow/internal/FlowSummaryImplSpecific.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll index 615578f8891..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) { From d13307e417ab3ae59f84febae4c6cae1f2510777 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:39:34 +0100 Subject: [PATCH 124/136] Swift: Rename Negative Summary Model to Neutral Model. --- .../swift/dataflow/internal/FlowSummaryImplSpecific.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 From ac2d55880c114c7673d0d1ad1fa3e7c5eac9ce74 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:40:16 +0100 Subject: [PATCH 125/136] Go: Rename Negative Summary Model to Neutral Model. --- .../go/dataflow/internal/FlowSummaryImplSpecific.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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] From 2cb88037a4b02eae88901b8b27907caa3e05ab5f Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 6 Dec 2022 16:51:09 +0100 Subject: [PATCH 126/136] C#/Java: Rename Negative Summary Model to Neutral Model in conversion and generator tooling. --- ...mmaryModels.ql => CaptureNeutralModels.ql} | 0 ...egativeSummaries.ql => ExtractNeutrals.ql} | 0 ...mmaryModels.ql => CaptureNeutralModels.ql} | 0 .../utils/model-generator/RegenerateModels.py | 2 +- ...egativeSummaries.ql => ExtractNeutrals.ql} | 0 .../models-as-data/convert_extensions.py | 4 ++-- .../models-as-data/generate_flow_model.py | 22 +++++++++---------- misc/scripts/models-as-data/helpers.py | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) rename csharp/ql/src/utils/model-generator/{CaptureNegativeSummaryModels.ql => CaptureNeutralModels.ql} (100%) rename csharp/ql/src/utils/modelconverter/{ExtractNegativeSummaries.ql => ExtractNeutrals.ql} (100%) rename java/ql/src/utils/model-generator/{CaptureNegativeSummaryModels.ql => CaptureNeutralModels.ql} (100%) rename java/ql/src/utils/modelconverter/{ExtractNegativeSummaries.ql => ExtractNeutrals.ql} (100%) diff --git a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureNeutralModels.ql similarity index 100% rename from csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql rename to csharp/ql/src/utils/model-generator/CaptureNeutralModels.ql diff --git a/csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql b/csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql similarity index 100% rename from csharp/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql rename to csharp/ql/src/utils/modelconverter/ExtractNeutrals.ql diff --git a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNeutralModels.ql similarity index 100% rename from java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql rename to java/ql/src/utils/model-generator/CaptureNeutralModels.ql diff --git a/java/ql/src/utils/model-generator/RegenerateModels.py b/java/ql/src/utils/model-generator/RegenerateModels.py index f89873339f5..a939a1e56eb 100755 --- a/java/ql/src/utils/model-generator/RegenerateModels.py +++ b/java/ql/src/utils/model-generator/RegenerateModels.py @@ -37,7 +37,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 100% rename from java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql rename to java/ql/src/utils/modelconverter/ExtractNeutrals.ql 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..0c37c7f8309 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,10 +168,10 @@ 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. @@ -181,7 +181,7 @@ extensions: {sinkAddsTo} {sourceAddsTo} {summaryAddsTo} -{negativeSummaryAddsTo} +{neutralAddsTo} """ def makeTypeBasedContent(self): 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} From 1d103f57a0600ee2c4bb9ef7a4abaaa2463d2dc7 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 7 Dec 2022 09:34:52 +0100 Subject: [PATCH 127/136] C#/Java: Rename CaptureNegativeSummaryModels test to CaptureNeutralModels. --- .../model-generator/dataflow/CaptureNegativeSummaryModels.qlref | 1 - ...ativeSummaryModels.expected => CaptureNeutralModels.expected} | 0 .../utils/model-generator/dataflow/CaptureNeutralModels.qlref | 1 + .../model-generator/dataflow/CaptureNegativeSummaryModels.qlref | 1 - ...ativeSummaryModels.expected => CaptureNeutralModels.expected} | 0 .../utils/model-generator/dataflow/CaptureNeutralModels.qlref | 1 + 6 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref rename csharp/ql/test/utils/model-generator/dataflow/{CaptureNegativeSummaryModels.expected => CaptureNeutralModels.expected} (100%) create mode 100644 csharp/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref delete mode 100644 java/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref rename java/ql/test/utils/model-generator/dataflow/{CaptureNegativeSummaryModels.expected => CaptureNeutralModels.expected} (100%) create mode 100644 java/ql/test/utils/model-generator/dataflow/CaptureNeutralModels.qlref 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/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 From 1a226a15bf383d46512fe6e1322022e5f4a6aca3 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 7 Dec 2022 10:35:38 +0100 Subject: [PATCH 128/136] C#/Java: Cleanup up printing of generated models. --- .../models-as-data/generate_flow_model.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/misc/scripts/models-as-data/generate_flow_model.py b/misc/scripts/models-as-data/generate_flow_model.py index 0c37c7f8309..30f90000d4c 100644 --- a/misc/scripts/models-as-data/generate_flow_model.py +++ b/misc/scripts/models-as-data/generate_flow_model.py @@ -173,16 +173,10 @@ Requirements: `codeql` should both appear on your path. else: 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} -{neutralAddsTo} - """ +{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: From 67732cbfa056b3d1d5345ee648e86c3a946ba2d7 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 7 Dec 2022 10:39:26 +0100 Subject: [PATCH 129/136] Java: Remove unneeded import for RegenerateModels.py. --- java/ql/src/utils/model-generator/RegenerateModels.py | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/src/utils/model-generator/RegenerateModels.py b/java/ql/src/utils/model-generator/RegenerateModels.py index a939a1e56eb..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 From 4835d148655d776511306a21f642d9bac2821e45 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 9 Dec 2022 15:11:49 +0100 Subject: [PATCH 130/136] Java/C#: Delete the deprecated NeutralModelCsv class. --- .../code/csharp/dataflow/ExternalFlow.qll | 27 ------------------- .../code/java/dataflow/ExternalFlow.qll | 27 ------------------- 2 files changed, 54 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll index e6e98a9d222..2664c25280b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll @@ -132,28 +132,12 @@ private class SummaryModelCsvInternal extends Unit { abstract predicate row(string row); } -/** - * DEPRECATED: Define neutral models as data extensions instead. - * - * A unit class for adding additional neutral model rows. - * - * Extend this class to add additional neutral definitions. - */ -deprecated class NeutralModelCsv = NeutralModelCsvInternal; - -private class NeutralModelCsvInternal extends Unit { - /** Holds if `row` specifies a neutral 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 neutralModelInternal(string row) { any(NeutralModelCsvInternal s).row(row) } - /** * Holds if a source model exists for the given parameters. */ @@ -250,15 +234,6 @@ extensible predicate extNeutralModel( predicate neutralModel( string namespace, string type, string name, string signature, string provenance ) { - exists(string row | - neutralModelInternal(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 extNeutralModel(namespace, type, name, signature, provenance) } @@ -391,8 +366,6 @@ module ModelValidation { sinkModelInternal(row) and expect = 9 and pred = "sink" or summaryModelInternal(row) and expect = 10 and pred = "summary" - or - neutralModelInternal(row) and expect = 5 and pred = "neutral" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index f3465cad3f9..10084c17c8d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -122,28 +122,12 @@ private class SummaryModelCsvInternal extends Unit { abstract predicate row(string row); } -/** - * DEPRECATED: Define neutral models as data extensions instead. - * - * A unit class for adding additional neutral model rows. - * - * Extend this class to add additional neutral definitions. - */ -deprecated class NeutralModelCsv = NeutralModelCsvInternal; - -private class NeutralModelCsvInternal extends Unit { - /** Holds if `row` specifies a neutral 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 neutralModelInternal(string row) { any(NeutralModelCsvInternal s).row(row) } - /** * Holds if an experimental source model exists for the given parameters. * This is only for experimental queries. @@ -318,15 +302,6 @@ extensible predicate extNeutralModel( /** 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) { - exists(string row | - neutralModelInternal(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 extNeutralModel(package, type, name, signature, provenance) } @@ -468,8 +443,6 @@ module ModelValidation { sinkModelInternal(row) and expect = 9 and pred = "sink" or summaryModelInternal(row) and expect = 10 and pred = "summary" - or - neutralModelInternal(row) and expect = 5 and pred = "neutral" | exists(int cols | cols = 1 + max(int n | exists(row.splitAt(";", n))) and From 5282c86158d1e0eae1e68618c583d6040f558116 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 9 Dec 2022 18:07:14 +0000 Subject: [PATCH 131/136] Apply review feedback --- .../src/main/kotlin/KotlinFileExtractor.kt | 10 ++++------ .../kotlin/nullability-annotations/test.py | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 252bd97fa33..fcc19ec7fd2 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -217,7 +217,8 @@ open class KotlinFileExtractor( is IrField -> { val parentId = useDeclarationParent(getFieldParent(declaration), false)?.cast() if (parentId != null) { - extractField(declaration, parentId, extractFunctionBodies) + // 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 } @@ -496,7 +497,7 @@ open class KotlinFileExtractor( private fun replaceKotlinDeprecatedAnnotation(annotations: List): List { val shouldReplace = annotations.any { (it.type as? IrSimpleType)?.classFqName?.asString() == "kotlin.Deprecated" } && - annotations.none { (it.type as? IrSimpleType)?.classFqName?.asString() == "java.lang.Deprecated" } + annotations.none { it.type.classOrNull == javaLangDeprecated?.symbol } val jldConstructor = javaLangDeprecatedConstructor if (!shouldReplace || jldConstructor == null) return annotations @@ -508,10 +509,7 @@ open class KotlinFileExtractor( } private fun extractAnnotations(c: IrAnnotationContainer, annotations: List, parent: Label, extractEnumTypeAccesses: Boolean) { - val origin = when(c) { - is IrDeclaration -> c.origin - else -> null - } + 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) 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 index 4072b3d454e..6a27fa40a40 100644 --- a/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py +++ b/java/ql/integration-tests/all-platforms/kotlin/nullability-annotations/test.py @@ -1,6 +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:out2 -d out3"], lang="java") +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") From 331fab5ac0d1239730e0dfddabfdce6b43cfdaa4 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 9 Dec 2022 23:03:36 +0100 Subject: [PATCH 132/136] C++: Generalize the `ArgvSource` flow source This matches `isUserInput` and handles cases where `argv` has a different name, which is allowed. --- cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll index d2c90a38075..8bc059da506 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll @@ -89,9 +89,9 @@ private class LocalParameterSource 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() ) } From 1e1974c9fbc8e45fa14d9a3495b89e0a2416b387 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 9 Dec 2022 23:17:36 +0100 Subject: [PATCH 133/136] C++: Add change note --- cpp/ql/lib/change-notes/2022-12-09-generalize-argv-source.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2022-12-09-generalize-argv-source.md 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`. From 9dc26140129223bdb094f793213cf018e41fcaae Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 9 Dec 2022 23:10:58 +0100 Subject: [PATCH 134/136] C++: Make all flow source descriptions start with a lower case letter In every context where we use the description a lower case letter makes more sense. --- .../lib/semmle/code/cpp/models/implementations/Fread.qll | 2 +- .../semmle/code/cpp/models/implementations/GetDelim.qll | 2 +- .../lib/semmle/code/cpp/models/implementations/Gets.qll | 8 ++++---- .../lib/semmle/code/cpp/models/implementations/Inet.qll | 2 +- .../lib/semmle/code/cpp/models/implementations/Recv.qll | 2 +- .../lib/semmle/code/cpp/models/implementations/Scanf.qll | 4 ++-- .../lib/semmle/code/cpp/models/implementations/Send.qll | 2 +- .../Security/CWE/CWE-129/ImproperArrayIndexValidation.ql | 6 +----- 8 files changed, 12 insertions(+), 16 deletions(-) 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 2589c6f46a4..c0c4537b746 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Inet.qll @@ -158,6 +158,6 @@ private class Getaddrinfo extends TaintFunction, ArrayFunction, RemoteFlowSource override predicate hasRemoteFlowSource(FunctionOutput output, string description) { output.isParameterDeref(3) and - description = "Address returned by " + this.getName() + 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/Scanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll index 079a231a913..9a9e02611f8 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll @@ -74,7 +74,7 @@ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, 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() + description = "value read by " + this.getName() } } @@ -84,7 +84,7 @@ private class ScanfModel extends ScanfFunctionModel, LocalFlowSourceFunction ins 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() + description = "value read by " + this.getName() } } 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/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 From ce92ba640a36193ecc680887fb43b0585d8ec4a2 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 9 Dec 2022 23:38:03 +0100 Subject: [PATCH 135/136] C++: Accept test changes --- .../semmle/ExecTainted/ExecTainted.expected | 22 +++++++++---------- .../tests/CleartextBufferWrite.expected | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) 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 5542eac5d3a..20be1550401 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 @@ -163,17 +163,17 @@ subpaths #select | test.cpp:23:12:23:19 | command1 | test.cpp:16:20:16:23 | argv | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:16:20:16:23 | argv | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument | | test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv | test.cpp:51:10:51:16 | command 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 | 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 | command 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 | command 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 | path 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 | command 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 | command 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 | path 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 to operator+ | call to operator+ | | 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:17:114:17 | Call | Call | | 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 | Call | -| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 | command 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 cece7f64714..23850de9418 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 @@ -6,5 +6,5 @@ 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: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) | | 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) | From beb66d027e067aab77ffe2e1f7200d78f8140019 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 9 Dec 2022 13:43:13 +0100 Subject: [PATCH 136/136] C++: Use `FlowSource` in `cpp/path-injection` --- .../src/Security/CWE/CWE-022/TaintedPath.ql | 35 ++++--------------- .../SAMATE/TaintedPath/TaintedPath.expected | 2 +- .../CWE-022/semmle/tests/TaintedPath.expected | 10 +++--- 3 files changed, 12 insertions(+), 35 deletions(-) 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/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected index a4f42c91796..3c9571780d7 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected @@ -5,4 +5,4 @@ nodes | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection | subpaths #select -| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | user input (fgets) | +| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | user input (string read by fgets) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 45ca662513d..f4bf42b031f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -2,7 +2,6 @@ edges | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection | | test.c:31:22:31:25 | argv | test.c:32:11:32:18 | fileName indirection | | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | -| test.c:43:17:43:24 | fileName | test.c:44:11:44:18 | fileName indirection | | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | nodes | test.c:9:23:9:26 | argv | semmle.label | argv | @@ -11,12 +10,11 @@ nodes | test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection | | test.c:37:17:37:24 | scanf output argument | semmle.label | scanf output argument | | test.c:38:11:38:18 | fileName indirection | semmle.label | fileName indirection | -| test.c:43:17:43:24 | fileName | semmle.label | fileName | | test.c:43:17:43:24 | scanf output argument | semmle.label | scanf output argument | | test.c:44:11:44:18 | fileName indirection | semmle.label | fileName indirection | subpaths #select -| test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:9:23:9:26 | argv | user input (argv) | -| test.c:32:11:32:18 | fileName | test.c:31:22:31:25 | argv | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:31:22:31:25 | argv | user input (argv) | -| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | fileName | user input (scanf) | -| test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | fileName | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | fileName | user input (scanf) | +| test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:9:23:9:26 | argv | user input (a command-line argument) | +| test.c:32:11:32:18 | fileName | test.c:31:22:31:25 | argv | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:31:22:31:25 | argv | user input (a command-line argument) | +| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | scanf output argument | user input (value read by scanf) | +| test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | scanf output argument | user input (value read by scanf) |