From 54582031d835da8c52ea2c70e7b1fb632fbc30ef Mon Sep 17 00:00:00 2001 From: amammad Date: Thu, 16 Feb 2023 17:14:32 +0100 Subject: [PATCH 01/96] v1 --- .../Security/CWE-074/paramiko/paramiko.qhelp | 17 +++++ .../Security/CWE-074/paramiko/paramiko.ql | 72 +++++++++++++++++++ .../Security/CWE-074/paramiko/paramikoBad.py | 36 ++++++++++ .../CWE-074/paramiko/paramiko.expected | 16 +++++ .../Security/CWE-074/paramiko/paramiko.py | 27 +++++++ .../Security/CWE-074/paramiko/paramiko.qlref | 1 + 6 files changed, 169 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.qhelp create mode 100644 python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql create mode 100644 python/ql/src/experimental/Security/CWE-074/paramiko/paramikoBad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.qhelp b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.qhelp new file mode 100644 index 00000000000..98cc0e1e4de --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.qhelp @@ -0,0 +1,17 @@ + + + +

+ Processing an unvalidated user input can allow an attacker to inject arbitrary command in your local and remote servers when creating a ssh connection. +

+
+ +

+ This vulnerability can be prevented by not allowing untrusted user input to be passed as ProxyCommand or exec_command. +

+
+ +

In the example below, the ProxyCommand and exec_command are controlled by the user and hence leads to a vulnerability.

+ +
+
diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql new file mode 100644 index 00000000000..28db4e129b4 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql @@ -0,0 +1,72 @@ +/** + * @name RCE with user provided command with paramiko ssh client + * @description user provided command can lead to execute code on a external server that can be belong to other users or admins + * @kind path-problem + * @problem.severity error + * @security-severity 9.3 + * @precision high + * @id py/command-injection + * @tags security + * experimental + * external/cwe/cwe-074 + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.ApiGraphs +import DataFlow::PathGraph + +class ParamikoCMDInjectionConfiguration extends TaintTracking::Configuration { + ParamikoCMDInjectionConfiguration() { this = "ParamikoCMDInjectionConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = + [ + API::moduleImport("paramiko") + .getMember("SSHClient") + .getReturn() + .getMember("exec_command") + .getACall() + .getArgByName("command"), + API::moduleImport("paramiko") + .getMember("SSHClient") + .getReturn() + .getMember("exec_command") + .getACall() + .getArg(0) + ] + or + sink = + [ + API::moduleImport("paramiko") + .getMember("SSHClient") + .getReturn() + .getMember("connect") + .getACall() + .getArgByName("sock"), + API::moduleImport("paramiko") + .getMember("SSHClient") + .getReturn() + .getMember("connect") + .getACall() + .getArg(11) + ] + } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(API::CallNode call | + call = API::moduleImport("paramiko").getMember("ProxyCommand").getACall() and + nodeFrom = [call.getArg(0), call.getArgByName("command_line")] and + nodeTo = call + ) + } +} + +from ParamikoCMDInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "This code execution depends on a $@.", source.getNode(), + "a user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramikoBad.py b/python/ql/src/experimental/Security/CWE-074/paramiko/paramikoBad.py new file mode 100644 index 00000000000..b54a88f2e4a --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramikoBad.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +from flask import request, Flask +import paramiko +from paramiko import SSHClient + +app = Flask(__name__) +paramiko_ssh_client = SSHClient() +paramiko_ssh_client.load_system_host_keys() +paramiko_ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +paramiko_ssh_client.connect(hostname="127.0.0.1", port="22", username="ssh_user_name", pkey="k", timeout=11, banner_timeout=200) + + +@app.route('/external_exec_command_1') +def bad1(): + user_cmd = request.args.get('command') + stdin, stdout, stderr = paramiko_ssh_client.exec_command(user_cmd) + return stdout + +@app.route('/external_exec_command_2') +def bad2(): + user_cmd = request.args.get('command') + stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=user_cmd) + return stdout + + +@app.route('/proxycommand') +def bad2(): + user_cmd = request.args.get('command') + stdin, stdout, stderr = paramiko_ssh_client.connect('hostname', username='user',password='yourpassword',sock=paramiko.ProxyCommand(user_cmd)) + return stdout + +if __name__ == '__main__': + app.debug = False + app.run() + diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected new file mode 100644 index 00000000000..85e1e7b326d --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.expected @@ -0,0 +1,16 @@ +edges +| paramiko.py:15:21:15:23 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd | +| paramiko.py:20:21:20:23 | ControlFlowNode for cmd | paramiko.py:21:70:21:72 | ControlFlowNode for cmd | +| paramiko.py:25:21:25:23 | ControlFlowNode for cmd | paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() | +nodes +| paramiko.py:15:21:15:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| paramiko.py:20:21:20:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| paramiko.py:21:70:21:72 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| paramiko.py:25:21:25:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +subpaths +#select +| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | paramiko.py:15:21:15:23 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd | This code execution depends on a $@. | paramiko.py:15:21:15:23 | ControlFlowNode for cmd | a user-provided value | +| paramiko.py:21:70:21:72 | ControlFlowNode for cmd | paramiko.py:20:21:20:23 | ControlFlowNode for cmd | paramiko.py:21:70:21:72 | ControlFlowNode for cmd | This code execution depends on a $@. | paramiko.py:20:21:20:23 | ControlFlowNode for cmd | a user-provided value | +| paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() | paramiko.py:25:21:25:23 | ControlFlowNode for cmd | paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() | This code execution depends on a $@. | paramiko.py:25:21:25:23 | ControlFlowNode for cmd | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py new file mode 100644 index 00000000000..1e625d18345 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +from fastapi import FastAPI +import paramiko +from paramiko import SSHClient +paramiko_ssh_client = SSHClient() +paramiko_ssh_client.load_system_host_keys() +paramiko_ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +paramiko_ssh_client.connect(hostname="127.0.0.1", port="22", username="ssh_user_name", pkey="k", timeout=11, banner_timeout=200) + +app = FastAPI() + + +@app.get("/bad1") +async def read_item(cmd: str): + stdin, stdout, stderr = paramiko_ssh_client.exec_command(cmd) + return {"success": stdout} + +@app.get("/bad2") +async def read_item(cmd: str): + stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=cmd) + return {"success": "OK"} + +@app.get("/bad3") +async def read_item(cmd: str): + stdin, stdout, stderr = paramiko_ssh_client.connect('hostname', username='user',password='yourpassword',sock=paramiko.ProxyCommand(cmd)) + return {"success": "OK"} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref new file mode 100644 index 00000000000..8a164fcc8cc --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-074/paramiko/paramiko.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-074/paramiko/paramiko.ql \ No newline at end of file From 820db43945feb799928fbae4ed5253d030833dc7 Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:21:31 +0200 Subject: [PATCH 02/96] Add ERB Template Injection Sink --- ruby/ql/lib/codeql/ruby/frameworks/Rails.qll | 16 ++++++++++++++++ .../TemplateInjection/ErbInjection.rb | 7 +++++++ .../TemplateInjection/TemplateInjection.expected | 3 +++ 3 files changed, 26 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll index b2a9fef3c1c..42d038a303d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll @@ -400,3 +400,19 @@ private class AccessLocalsKeySummary extends SummarizedCallable { preservesValue = true } } + +/** A call to `render inline: foo`, considered as a ERB template rendering. */ +private class RailsTemplateRendering extends TemplateRendering::Range, DataFlow::CallNode { + private DataFlow::Node template; + + RailsTemplateRendering() { + ( + this.asExpr().getExpr() instanceof Rails::RenderCall + or + this.asExpr().getExpr() instanceof Rails::RenderToCall + ) and + template = this.getKeywordArgument("inline") + } + + override DataFlow::Node getTemplate() { result = template } +} diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/ErbInjection.rb b/ruby/ql/test/query-tests/experimental/TemplateInjection/ErbInjection.rb index f202fc146a7..41b9d706953 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/ErbInjection.rb +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/ErbInjection.rb @@ -14,6 +14,10 @@ class FooController < ActionController::Base # where name is unsanitized template = ERB.new(bad_text).result(binding) + # BAD: user input is evaluated + # where name is unsanitized + render inline: bad_text + # Template with the source good_text = " @@ -22,6 +26,9 @@ class FooController < ActionController::Base # GOOD: user input is not evaluated template2 = ERB.new(good_text).result(binding) + + # GOOD: user input is not evaluated + render inline: good_text end end diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected index a3e20d71b20..d7a76ef930a 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected @@ -4,6 +4,7 @@ edges | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:5:12:5:24 | ...[...] : | | ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:5:5:5:8 | name : | | ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:15:24:15:31 | bad_text | +| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:19:20:19:27 | bad_text | | ErbInjection.rb:8:16:11:14 | ... % ... : | ErbInjection.rb:8:5:8:12 | bad_text : | | ErbInjection.rb:11:11:11:14 | name : | ErbInjection.rb:8:16:11:14 | ... % ... : | | SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:8:5:8:12 | bad_text : | @@ -23,6 +24,7 @@ nodes | ErbInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | | ErbInjection.rb:11:11:11:14 | name : | semmle.label | name : | | ErbInjection.rb:15:24:15:31 | bad_text | semmle.label | bad_text | +| ErbInjection.rb:19:20:19:27 | bad_text | semmle.label | bad_text | | SlimInjection.rb:5:5:5:8 | name : | semmle.label | name : | | SlimInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | | SlimInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | @@ -35,5 +37,6 @@ nodes subpaths #select | ErbInjection.rb:15:24:15:31 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:15:24:15:31 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | +| ErbInjection.rb:19:20:19:27 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:19:20:19:27 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | | SlimInjection.rb:14:25:14:32 | bad_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:14:25:14:32 | bad_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | | SlimInjection.rb:23:25:23:33 | bad2_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:23:25:23:33 | bad2_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | From 64cf3adfd4e28441e11a2321f67b73e718ae6aba Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:29:14 +0200 Subject: [PATCH 03/96] Update examples --- ruby/ql/src/experimental/template-injection/examples/SSTIBad.rb | 1 + ruby/ql/src/experimental/template-injection/examples/SSTIGood.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/ruby/ql/src/experimental/template-injection/examples/SSTIBad.rb b/ruby/ql/src/experimental/template-injection/examples/SSTIBad.rb index 6ea7f4ed8c2..c464dfae2bf 100644 --- a/ruby/ql/src/experimental/template-injection/examples/SSTIBad.rb +++ b/ruby/ql/src/experimental/template-injection/examples/SSTIBad.rb @@ -9,6 +9,7 @@ class BadERBController < ActionController::Base

Hello %s

" % name template = ERB.new(html_text).result(binding) + render inline: html_text end end diff --git a/ruby/ql/src/experimental/template-injection/examples/SSTIGood.rb b/ruby/ql/src/experimental/template-injection/examples/SSTIGood.rb index 844f0115d7c..f2d33378968 100644 --- a/ruby/ql/src/experimental/template-injection/examples/SSTIGood.rb +++ b/ruby/ql/src/experimental/template-injection/examples/SSTIGood.rb @@ -9,6 +9,7 @@ class GoodController < ActionController::Base

Hello <%= name %>

" template = ERB.new(html_text).result(binding) + render inline: html_text end end From ec97cdc8a0206fc76ef3ca48b92ee8a043880c7a Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Thu, 13 Apr 2023 23:16:20 -0400 Subject: [PATCH 04/96] Allow NonKeyCiphers to include truncated SHA-512 MDs in Forge JS library. --- .../lib/change-notes/2023-04-13-Forge-truncated-sha512-hash | 5 +++++ .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash diff --git a/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash b/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash new file mode 100644 index 00000000000..391b0bb7109 --- /dev/null +++ b/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* The Forge module in `CryptoLibraries.qll` now correctly classifies SHA-512/224, +* SHA-512/256, and SHA-512/384 hashes used in message digests as NonKeyCiphers. \ No newline at end of file diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 2fab10eacac..00332b6530e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -627,6 +627,10 @@ private module Forge { // require("forge").md.md5.create().update('The quick brown fox jumps over the lazy dog'); this = getAnImportNode().getMember("md").getMember(algorithmName).getMember("create").getACall() + or + // require("forge").sha512.sha256.create().update('The quick brown fox jumps over the lazy dog'); + this = + getAnImportNode().getMember("md").getMember(algorithmName).getAMember().getMember("create").getACall() ) } From 1c2fdc8df948173721b67a46c7c04d93b81cc242 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 19 Apr 2023 10:29:14 +0200 Subject: [PATCH 05/96] JS: Ignore more webpack modules --- .../semmle/javascript/frameworks/Bundling.qll | 24 ++++++++++++++++--- .../security/regexp/RegExpTreeView.qll | 7 +++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll index 1315ac651d5..a57d73a252f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll @@ -106,10 +106,10 @@ private predicate isBrowserifyDependencyMap(ObjectExpr deps) { * or their name must contain the substring "webpack_require" * or "webpack_module_template_argument". */ -private predicate isWebpackModule(FunctionExpr m) { +private predicate isWebpackModule(Function m) { forex(Parameter parm | parm = m.getAParameter() | exists(string name | name = parm.getName() | - name.regexpMatch("module|exports|.*webpack_require.*|.*webpack_module_template_argument.*") + name.regexpMatch("module|exports|.*webpack_require.*|.*webpack_module_template_argument.*|.*unused_webpack_module.*") ) ) } @@ -161,6 +161,23 @@ predicate isWebpackBundle(ArrayExpr ae) { ) } +/** + * Holds if `object` looks like a Webpack bundle of form: + * ```javascript + * var __webpack_modules__ = ({ + * "file1": ((module, __webpack__exports__, __webpack_require__) => ...) + * ... + * }) + * ``` + */ +predicate isWebpackNamedBundle(ObjectExpr object) { + isWebpackModule(object.getAProperty().getInit().getUnderlyingValue()) and + exists(VarDef def | + def.getSource().(Expr).getUnderlyingValue() = object and + def.getTarget().(VarRef).getName() = "__webpack_modules__" + ) +} + /** * Holds if `tl` is a collection of concatenated files by [atpackager](https://github.com/ariatemplates/atpackager). */ @@ -233,7 +250,8 @@ predicate isDirectiveBundle(TopLevel tl) { exists(BundleDirective d | d.getTopLe predicate isBundle(TopLevel tl) { exists(Expr e | e.getTopLevel() = tl | isBrowserifyBundle(e) or - isWebpackBundle(e) + isWebpackBundle(e) or + isWebpackNamedBundle(e) ) or isMultiPartBundle(tl) diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll index d4440ed7db5..e5aa0e490fa 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll @@ -4,6 +4,7 @@ private import codeql.regex.nfa.NfaUtils as NfaUtils private import codeql.regex.RegexTreeView +private import semmle.javascript.frameworks.Bundling /** An implementation that parses a regular expression into a tree of `RegExpTerm`s. */ module RegExpTreeView implements RegexTreeViewSig { @@ -42,7 +43,11 @@ module RegExpTreeView implements RegexTreeViewSig { * * For javascript we make the pragmatic performance optimization to ignore minified files. */ - predicate isExcluded(RegExpParent parent) { parent.(Expr).getTopLevel().isMinified() } + predicate isExcluded(RegExpParent parent) { + parent.(Expr).getTopLevel().isMinified() + or + isBundle(parent.(Expr).getTopLevel()) + } /** * Holds if `root` has the `i` flag for case-insensitive matching. From 31b56bf9660d7c7a5738cd9dd806086da1b947ef Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Wed, 19 Apr 2023 13:32:23 -0400 Subject: [PATCH 06/96] Update javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash Co-authored-by: Asger F --- .../ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash b/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash index 391b0bb7109..1d2bfc9a8f9 100644 --- a/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash +++ b/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash @@ -2,4 +2,4 @@ category: minorAnalysis --- * The Forge module in `CryptoLibraries.qll` now correctly classifies SHA-512/224, -* SHA-512/256, and SHA-512/384 hashes used in message digests as NonKeyCiphers. \ No newline at end of file + SHA-512/256, and SHA-512/384 hashes used in message digests as NonKeyCiphers. \ No newline at end of file From 4f7275f064bbdbf6745a507cd9a27ede6d19d912 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Wed, 19 Apr 2023 13:39:18 -0400 Subject: [PATCH 07/96] Reformat doc and move change note --- .../lib/semmle/javascript/frameworks/CryptoLibraries.qll | 7 ++++++- .../2023-04-13-Forge-truncated-sha512-hash.md} | 0 2 files changed, 6 insertions(+), 1 deletion(-) rename javascript/ql/{lib/change-notes/2023-04-13-Forge-truncated-sha512-hash => src/change-notes/2023-04-13-Forge-truncated-sha512-hash.md} (100%) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 00332b6530e..e5425b2fb88 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -630,7 +630,12 @@ private module Forge { or // require("forge").sha512.sha256.create().update('The quick brown fox jumps over the lazy dog'); this = - getAnImportNode().getMember("md").getMember(algorithmName).getAMember().getMember("create").getACall() + getAnImportNode() + .getMember("md") + .getMember(algorithmName) + .getAMember() + .getMember("create") + .getACall() ) } diff --git a/javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash b/javascript/ql/src/change-notes/2023-04-13-Forge-truncated-sha512-hash.md similarity index 100% rename from javascript/ql/lib/change-notes/2023-04-13-Forge-truncated-sha512-hash rename to javascript/ql/src/change-notes/2023-04-13-Forge-truncated-sha512-hash.md From 1acc0d2ddfd9ac294d50aa4961eacec136b1a500 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Apr 2023 12:47:13 +0200 Subject: [PATCH 08/96] JS: Update model of js-yaml --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 1 + .../UnsafeDeserializationCustomizations.qll | 39 ++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 64175a848b2..c543607e73f 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -491,6 +491,7 @@ module API { * In other words, the value of a use of `that` may flow into the right-hand side of a * definition of this node. */ + pragma[inline] predicate refersTo(Node that) { this.asSink() = that.getAValueReachableFromSource() } /** diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll index a234a2d8829..eb3c10e37cd 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll @@ -25,25 +25,36 @@ module UnsafeDeserialization { /** A source of remote user input, considered as a flow source for unsafe deserialization. */ class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource { } + private API::Node unsafeYamlSchema() { + result = API::moduleImport("js-yaml").getMember("DEFAULT_FULL_SCHEMA") // from older versions + or + result = API::moduleImport("js-yaml-js-types").getMember(["all", "function"]) + or + result = unsafeYamlSchema().getMember("extend").getReceiver() + or + exists(API::CallNode call | + call.getAParameter().refersTo(unsafeYamlSchema()) and + call.getCalleeName() = "extend" and + result = call.getReturn() + ) + } + /** * An expression passed to one of the unsafe load functions of the `js-yaml` package. + * + * `js-yaml` since v4 defaults to being safe, but is unsafe when invoked with a schema + * that permits unsafe values. */ class JsYamlUnsafeLoad extends Sink { JsYamlUnsafeLoad() { - exists(DataFlow::ModuleImportNode mi | mi.getPath() = "js-yaml" | - // the first argument to a call to `load` or `loadAll` - exists(string n | n = "load" or n = "loadAll" | this = mi.getAMemberCall(n).getArgument(0)) - or - // the first argument to a call to `safeLoad` or `safeLoadAll` where - // the schema is specified to be `DEFAULT_FULL_SCHEMA` - exists(string n, DataFlow::CallNode c, DataFlow::Node fullSchema | - n = "safeLoad" or n = "safeLoadAll" - | - c = mi.getAMemberCall(n) and - this = c.getArgument(0) and - fullSchema = c.getOptionArgument(c.getNumArgument() - 1, "schema") and - mi.getAPropertyRead("DEFAULT_FULL_SCHEMA").flowsTo(fullSchema) - ) + exists(API::CallNode call | + // Note: we include the old 'safeLoad' and 'safeLoadAll' functon because they were also unsafe when invoked with an unsafe schema. + call = + API::moduleImport("js-yaml") + .getMember(["load", "loadAll", "safeLoad", "safeLoadAll"]) + .getACall() and + call.getAParameter().getMember("schema").refersTo(unsafeYamlSchema()) and + this = call.getArgument(0) ) } } From 1d0a0dec6fbf837e3d6a0572c64556f37ade925a Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 20 Apr 2023 12:48:17 +0200 Subject: [PATCH 09/96] JS: Fix typo --- .../security/dataflow/UnsafeDeserializationCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll index eb3c10e37cd..6871ac93b8e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll @@ -30,7 +30,7 @@ module UnsafeDeserialization { or result = API::moduleImport("js-yaml-js-types").getMember(["all", "function"]) or - result = unsafeYamlSchema().getMember("extend").getReceiver() + result = unsafeYamlSchema().getMember("extend").getReturn() or exists(API::CallNode call | call.getAParameter().refersTo(unsafeYamlSchema()) and From 64ea4833d9ed642d969067e4651d9ce23041a092 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 18 Apr 2023 15:07:28 -0400 Subject: [PATCH 10/96] Erase generics in `typeAsModel` --- .../utils/modelgenerator/internal/CaptureModelsSpecific.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 249dcb4379f..c1e30d308f2 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -104,7 +104,9 @@ private string isExtensible(J::RefType ref) { } private string typeAsModel(J::RefType type) { - result = type.getCompilationUnit().getPackage().getName() + ";" + type.nestedName() + result = + type.getCompilationUnit().getPackage().getName() + ";" + + type.getErasure().(J::RefType).nestedName() } private J::RefType bestTypeForModel(TargetApiSpecific api) { From 6e31f64aaa9bac09d8658456e67c5da79f014bdb Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Nov 2022 20:21:09 +0100 Subject: [PATCH 11/96] Python: Add test for dictionary flow --- .../dataflow/fieldflow/test_dict.py | 73 +++++++++++++++++++ .../test/experimental/dataflow/validTest.py | 1 + 2 files changed, 74 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/fieldflow/test_dict.py diff --git a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py new file mode 100644 index 00000000000..718dba747ca --- /dev/null +++ b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py @@ -0,0 +1,73 @@ +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) # $ unresolved_call=sys.path.append(..) +from testlib import expects + +# These are defined so that we can evaluate the test code. +NONSOURCE = "not a source" +SOURCE = "source" + + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + + +def SINK(x): + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) + + +def SINK_F(x): + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") + + +# ------------------------------------------------------------------------------ +# Actual tests +# ------------------------------------------------------------------------------ + +@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_dict_literal(): + d = {"key": SOURCE} + SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" + SINK(d.get("key")) # $ MISSING: flow + SINK(d.setdefault("key", NONSOURCE)) # $ MISSING: flow + + +@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_dict_update(): + d = {} + d["key"] = SOURCE + SINK(d["key"]) # $ MISSING: flow + SINK(d.get("key")) # $ MISSING: flow + SINK(d.setdefault("key", NONSOURCE)) # $ MISSING: flow + + +@expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_dict_override(): + d = {} + d["key"] = SOURCE + SINK(d["key"]) # $ MISSING: flow + + d["key"] = NONSOURCE + SINK_F(d["key"]) + + +def test_dict_setdefault(): + d = {} + d.setdefault("key", SOURCE) + SINK(d["key"]) # $ MISSING: flow + + +@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_dict_nonstring_key(): + d = {} + d[42] = SOURCE + SINK(d[42]) # $ MISSING: flow + SINK(d.get(42)) # $ MISSING: flow + SINK(d.setdefault(42, NONSOURCE)) # $ MISSING: flow diff --git a/python/ql/test/experimental/dataflow/validTest.py b/python/ql/test/experimental/dataflow/validTest.py index eeb6604ce7a..83533ce5831 100644 --- a/python/ql/test/experimental/dataflow/validTest.py +++ b/python/ql/test/experimental/dataflow/validTest.py @@ -72,6 +72,7 @@ if __name__ == "__main__": check_tests_valid("variable-capture.collections") check_tests_valid("module-initialization.multiphase") check_tests_valid("fieldflow.test") + check_tests_valid("fieldflow.test_dict") check_tests_valid_after_version("match.test", (3, 10)) check_tests_valid("exceptions.test") check_tests_valid_after_version("exceptions.test_group", (3, 11)) From b56869551d1b5c172476b5ef6cfcf0bd1ef4ff66 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Nov 2022 20:26:42 +0100 Subject: [PATCH 12/96] Python: Support more dictionary read/store steps The `setdefault` behavior is kinda strange, but no reason not to support it. --- .../2022-11-15-dictionary-read-store-steps.md | 4 ++ .../dataflow/new/internal/DataFlowPrivate.qll | 40 ++++++++++++++++++- .../dataflow/fieldflow/test_dict.py | 14 +++---- 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 python/ql/lib/change-notes/2022-11-15-dictionary-read-store-steps.md diff --git a/python/ql/lib/change-notes/2022-11-15-dictionary-read-store-steps.md b/python/ql/lib/change-notes/2022-11-15-dictionary-read-store-steps.md new file mode 100644 index 00000000000..45b225bbb26 --- /dev/null +++ b/python/ql/lib/change-notes/2022-11-15-dictionary-read-store-steps.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added more content-flow/field-flow for dictionaries, by adding support for reads through `mydict.get("key")` and `mydict.setdefault("key", value)`, and store steps through `dict["key"] = value` and `mydict.setdefault("key", value)`. diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 2bd2f7ec0ce..2b2b22ed3ce 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -688,17 +688,38 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo } /** Data flows from an element of a dictionary to the dictionary at a specific key. */ -predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, CfgNode nodeTo) { +predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) { // Dictionary // `{..., "key" = 42, ...}` // nodeFrom is `42`, cfg node // nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node // c denotes element of dictionary and the key `"key"` exists(KeyValuePair item | - item = nodeTo.getNode().(DictNode).getNode().(Dict).getAnItem() and + item = nodeTo.asCfgNode().(DictNode).getNode().(Dict).getAnItem() and nodeFrom.getNode().getNode() = item.getValue() and c.getKey() = item.getKey().(StrConst).getS() ) + or + exists(SubscriptNode subscript | + nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and + nodeFrom.asCfgNode() = subscript.(DefinitionNode).getValue() and + c.getKey() = subscript.getIndex().getNode().(StrConst).getText() + ) + or + // see https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault + exists(MethodCallNode call | + call.calls(nodeTo.(PostUpdateNode).getPreUpdateNode(), ["setdefault"]) and + call.getArg(0).asExpr().(StrConst).getText() = c.(DictionaryElementContent).getKey() and + nodeFrom = call.getArg(1) + ) +} + +predicate dictClearStep(Node node, DictionaryElementContent c) { + exists(SubscriptNode subscript | + subscript instanceof DefinitionNode and + node.asCfgNode() = subscript.getObject() and + c.getKey() = subscript.getIndex().getNode().(StrConst).getText() + ) } /** Data flows from an element expression in a comprehension to the comprehension. */ @@ -761,6 +782,8 @@ predicate defaultValueFlowStep(CfgNode nodeFrom, CfgNode nodeTo) { predicate readStep(Node nodeFrom, Content c, Node nodeTo) { subscriptReadStep(nodeFrom, c, nodeTo) or + dictReadStep(nodeFrom, c, nodeTo) + or iterableUnpackingReadStep(nodeFrom, c, nodeTo) or matchReadStep(nodeFrom, c, nodeTo) @@ -799,6 +822,17 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { ) } +predicate dictReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { + // see + // - https://docs.python.org/3.10/library/stdtypes.html#dict.get + // - https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault + exists(MethodCallNode call | + call.calls(nodeFrom, ["get", "setdefault"]) and + call.getArg(0).asExpr().(StrConst).getText() = c.(DictionaryElementContent).getKey() and + nodeTo = call + ) +} + /** Data flows from a sequence to a call to `pop` on the sequence. */ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { // set.pop or list.pop @@ -873,6 +907,8 @@ predicate clearsContent(Node n, Content c) { or attributeClearStep(n, c) or + dictClearStep(n, c) + or FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c) or dictSplatParameterNodeClearStep(n, c) diff --git a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py index 718dba747ca..3f73d382fb1 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py +++ b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py @@ -35,24 +35,24 @@ def SINK_F(x): def test_dict_literal(): d = {"key": SOURCE} SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" - SINK(d.get("key")) # $ MISSING: flow - SINK(d.setdefault("key", NONSOURCE)) # $ MISSING: flow + SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)" + SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" @expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_update(): d = {} d["key"] = SOURCE - SINK(d["key"]) # $ MISSING: flow - SINK(d.get("key")) # $ MISSING: flow - SINK(d.setdefault("key", NONSOURCE)) # $ MISSING: flow + SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" + SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)" + SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" @expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_override(): d = {} d["key"] = SOURCE - SINK(d["key"]) # $ MISSING: flow + SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" d["key"] = NONSOURCE SINK_F(d["key"]) @@ -61,7 +61,7 @@ def test_dict_override(): def test_dict_setdefault(): d = {} d.setdefault("key", SOURCE) - SINK(d["key"]) # $ MISSING: flow + SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" @expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) From e0e978bd3effe96e477431522b928e9a0619f683 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 16 Nov 2022 16:22:39 +0100 Subject: [PATCH 13/96] Python: Fix ql4ql alerts --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 2b2b22ed3ce..cac72c97e9a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -708,8 +708,8 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT or // see https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault exists(MethodCallNode call | - call.calls(nodeTo.(PostUpdateNode).getPreUpdateNode(), ["setdefault"]) and - call.getArg(0).asExpr().(StrConst).getText() = c.(DictionaryElementContent).getKey() and + call.calls(nodeTo.(PostUpdateNode).getPreUpdateNode(), "setdefault") and + call.getArg(0).asExpr().(StrConst).getText() = c.getKey() and nodeFrom = call.getArg(1) ) } From f80a0916acaa32beda63bcbafc6b516c80ce2c5a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 21 Apr 2023 14:42:20 +0200 Subject: [PATCH 14/96] Python: Don't report get/setdefault as unresolved calls for dict tests --- .../dataflow/TestUtil/UnresolvedCalls.qll | 15 +++++++++------ .../dataflow/fieldflow/UnresolvedCalls.ql | 10 ++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll b/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll index b84f8e6f165..003d02ba530 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll @@ -9,14 +9,17 @@ class UnresolvedCallExpectations extends InlineExpectationsTest { override string getARelevantTag() { result = "unresolved_call" } + predicate unresolvedCall(CallNode call) { + not exists(DataFlowPrivate::DataFlowCall dfc | + exists(dfc.getCallable()) and dfc.getNode() = call + ) and + not DataFlowPrivate::resolveClassCall(call, _) and + not call = API::builtin(_).getACall().asCfgNode() + } + override predicate hasActualResult(Location location, string element, string tag, string value) { exists(location.getFile().getRelativePath()) and - exists(CallNode call | - not exists(DataFlowPrivate::DataFlowCall dfc | - exists(dfc.getCallable()) and dfc.getNode() = call - ) and - not DataFlowPrivate::resolveClassCall(call, _) and - not call = API::builtin(_).getACall().asCfgNode() and + exists(CallNode call | this.unresolvedCall(call) | location = call.getLocation() and tag = "unresolved_call" and value = prettyExpr(call.getNode()) and diff --git a/python/ql/test/experimental/dataflow/fieldflow/UnresolvedCalls.ql b/python/ql/test/experimental/dataflow/fieldflow/UnresolvedCalls.ql index c31dc161620..af73ca552fc 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/UnresolvedCalls.ql +++ b/python/ql/test/experimental/dataflow/fieldflow/UnresolvedCalls.ql @@ -1,2 +1,12 @@ import python import experimental.dataflow.TestUtil.UnresolvedCalls +private import semmle.python.dataflow.new.DataFlow + +class IgnoreDictMethod extends UnresolvedCallExpectations { + override predicate unresolvedCall(CallNode call) { + super.unresolvedCall(call) and + not any(DataFlow::MethodCallNode methodCall | + methodCall.getMethodName() in ["get", "setdefault"] + ).asCfgNode() = call + } +} From 4094ec5fcc4b8d3c514bdeab1d17e7fb0d9d93c8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 21 Apr 2023 14:43:24 +0200 Subject: [PATCH 15/96] Python: Change additional dict store/read steps to not affect taint-tracking --- .../python/dataflow/new/internal/DataFlowPrivate.qll | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index cac72c97e9a..fbd13887850 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -588,6 +588,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) { or dictStoreStep(nodeFrom, c, nodeTo) or + moreDictStoreSteps(nodeFrom, c, nodeTo) + or comprehensionStoreStep(nodeFrom, c, nodeTo) or iterableUnpackingStoreStep(nodeFrom, c, nodeTo) @@ -699,7 +701,15 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT nodeFrom.getNode().getNode() = item.getValue() and c.getKey() = item.getKey().(StrConst).getS() ) - or +} + +/** + * This has been made private since `dictStoreStep` is used by taint-tracking, and + * adding these extra steps made some alerts very noisy. + * + * TODO: Once TaintTracking no longer uses `dictStoreStep`, unify the two predicates. + */ +private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) { exists(SubscriptNode subscript | nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and nodeFrom.asCfgNode() = subscript.(DefinitionNode).getValue() and From b60cab254a3aa42875cbe883fd78098d1205dd1e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 21 Apr 2023 15:25:47 +0200 Subject: [PATCH 16/96] Python: Accept `.expected` change --- .../Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected index 94bd7276631..7039123492c 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected @@ -3,7 +3,8 @@ edges | UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | | UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | UnsafeUnpack.py:0:0:0:0 | ModuleVariableNode for UnsafeUnpack.request | | UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | -| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | +| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() | +| UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | | UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | | UnsafeUnpack.py:47:20:47:34 | ControlFlowNode for compressed_file | UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file | @@ -32,6 +33,7 @@ nodes | UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath | | UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | semmle.label | ControlFlowNode for local_ziped_path | From 7fa84a3613f585f48d67ce2b7d6e5ea746c47400 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 24 Apr 2023 12:19:59 +0200 Subject: [PATCH 17/96] Python: Only test UnsafeUnpacking with Python 3 Apparently the fixup of .expected in the latest commit was only required when extracting as Python 3, but not as Python 2... I honestly don't understand why. --- .../query-tests/Security/CWE-022-UnsafeUnpacking/options | 1 + 1 file changed, 1 insertion(+) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/options diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/options b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/options new file mode 100644 index 00000000000..89369a90996 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/options @@ -0,0 +1 @@ +semmle-extractor-options: --lang=3 --max-import-depth=1 From 7453533ba4d40fccb3b9375a7e648857b5fd0f93 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 24 Apr 2023 11:51:17 +0200 Subject: [PATCH 18/96] Python: Expand `setdefault` tests --- .../experimental/dataflow/fieldflow/test_dict.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py index 3f73d382fb1..19b60576191 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py +++ b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py @@ -31,22 +31,27 @@ def SINK_F(x): # Actual tests # ------------------------------------------------------------------------------ -@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +@expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_literal(): d = {"key": SOURCE} SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)" - SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" -@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +@expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_update(): d = {} d["key"] = SOURCE SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)" - SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" +@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) +def test_setdefault(): + d = {} + x = d.setdefault("key", SOURCE) + SINK(x) # $ MISSING: flow="SOURCE, l:-1 -> d.setdefault(..)" + SINK(d["key"]) # $ flow="SOURCE, l:-2 -> d['key']" + SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" @expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_override(): From 611a7060b4c9bf87fc5ffe6d1ba6152f37dd2e14 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 12:46:20 +0200 Subject: [PATCH 19/96] JS: Add tests --- .../Security/CWE-502/Consistency.expected | 0 .../Security/CWE-502/Consistency.ql | 3 + .../CWE-502/UnsafeDeserialization.expected | 60 ++++++++++++------- .../test/query-tests/Security/CWE-502/tst.js | 17 +++++- 4 files changed, 58 insertions(+), 22 deletions(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-502/Consistency.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-502/Consistency.ql diff --git a/javascript/ql/test/query-tests/Security/CWE-502/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-502/Consistency.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/Security/CWE-502/Consistency.ql b/javascript/ql/test/query-tests/Security/CWE-502/Consistency.ql new file mode 100644 index 00000000000..410d56326ef --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-502/Consistency.ql @@ -0,0 +1,3 @@ +import javascript +import semmle.javascript.security.dataflow.UnsafeDeserializationQuery +import testUtilities.ConsistencyChecking diff --git a/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected b/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected index 784489a4444..7abe0b7f559 100644 --- a/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected @@ -1,23 +1,43 @@ nodes -| tst.js:7:22:7:36 | req.params.data | -| tst.js:7:22:7:36 | req.params.data | -| tst.js:7:22:7:36 | req.params.data | -| tst.js:8:25:8:39 | req.params.data | -| tst.js:8:25:8:39 | req.params.data | -| tst.js:8:25:8:39 | req.params.data | -| tst.js:12:26:12:40 | req.params.data | -| tst.js:12:26:12:40 | req.params.data | -| tst.js:12:26:12:40 | req.params.data | -| tst.js:13:29:13:43 | req.params.data | -| tst.js:13:29:13:43 | req.params.data | -| tst.js:13:29:13:43 | req.params.data | +| tst.js:13:22:13:36 | req.params.data | +| tst.js:13:22:13:36 | req.params.data | +| tst.js:13:22:13:36 | req.params.data | +| tst.js:14:25:14:39 | req.params.data | +| tst.js:14:25:14:39 | req.params.data | +| tst.js:14:25:14:39 | req.params.data | +| tst.js:15:26:15:40 | req.params.data | +| tst.js:15:26:15:40 | req.params.data | +| tst.js:15:26:15:40 | req.params.data | +| tst.js:16:29:16:43 | req.params.data | +| tst.js:16:29:16:43 | req.params.data | +| tst.js:16:29:16:43 | req.params.data | +| tst.js:20:22:20:36 | req.params.data | +| tst.js:20:22:20:36 | req.params.data | +| tst.js:20:22:20:36 | req.params.data | +| tst.js:21:22:21:36 | req.params.data | +| tst.js:21:22:21:36 | req.params.data | +| tst.js:21:22:21:36 | req.params.data | +| tst.js:24:22:24:36 | req.params.data | +| tst.js:24:22:24:36 | req.params.data | +| tst.js:24:22:24:36 | req.params.data | +| tst.js:25:22:25:36 | req.params.data | +| tst.js:25:22:25:36 | req.params.data | +| tst.js:25:22:25:36 | req.params.data | edges -| tst.js:7:22:7:36 | req.params.data | tst.js:7:22:7:36 | req.params.data | -| tst.js:8:25:8:39 | req.params.data | tst.js:8:25:8:39 | req.params.data | -| tst.js:12:26:12:40 | req.params.data | tst.js:12:26:12:40 | req.params.data | -| tst.js:13:29:13:43 | req.params.data | tst.js:13:29:13:43 | req.params.data | +| tst.js:13:22:13:36 | req.params.data | tst.js:13:22:13:36 | req.params.data | +| tst.js:14:25:14:39 | req.params.data | tst.js:14:25:14:39 | req.params.data | +| tst.js:15:26:15:40 | req.params.data | tst.js:15:26:15:40 | req.params.data | +| tst.js:16:29:16:43 | req.params.data | tst.js:16:29:16:43 | req.params.data | +| tst.js:20:22:20:36 | req.params.data | tst.js:20:22:20:36 | req.params.data | +| tst.js:21:22:21:36 | req.params.data | tst.js:21:22:21:36 | req.params.data | +| tst.js:24:22:24:36 | req.params.data | tst.js:24:22:24:36 | req.params.data | +| tst.js:25:22:25:36 | req.params.data | tst.js:25:22:25:36 | req.params.data | #select -| tst.js:7:22:7:36 | req.params.data | tst.js:7:22:7:36 | req.params.data | tst.js:7:22:7:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:7:22:7:36 | req.params.data | user-provided value | -| tst.js:8:25:8:39 | req.params.data | tst.js:8:25:8:39 | req.params.data | tst.js:8:25:8:39 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:8:25:8:39 | req.params.data | user-provided value | -| tst.js:12:26:12:40 | req.params.data | tst.js:12:26:12:40 | req.params.data | tst.js:12:26:12:40 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:12:26:12:40 | req.params.data | user-provided value | -| tst.js:13:29:13:43 | req.params.data | tst.js:13:29:13:43 | req.params.data | tst.js:13:29:13:43 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:13:29:13:43 | req.params.data | user-provided value | +| tst.js:13:22:13:36 | req.params.data | tst.js:13:22:13:36 | req.params.data | tst.js:13:22:13:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:13:22:13:36 | req.params.data | user-provided value | +| tst.js:14:25:14:39 | req.params.data | tst.js:14:25:14:39 | req.params.data | tst.js:14:25:14:39 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:14:25:14:39 | req.params.data | user-provided value | +| tst.js:15:26:15:40 | req.params.data | tst.js:15:26:15:40 | req.params.data | tst.js:15:26:15:40 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:15:26:15:40 | req.params.data | user-provided value | +| tst.js:16:29:16:43 | req.params.data | tst.js:16:29:16:43 | req.params.data | tst.js:16:29:16:43 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:16:29:16:43 | req.params.data | user-provided value | +| tst.js:20:22:20:36 | req.params.data | tst.js:20:22:20:36 | req.params.data | tst.js:20:22:20:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:20:22:20:36 | req.params.data | user-provided value | +| tst.js:21:22:21:36 | req.params.data | tst.js:21:22:21:36 | req.params.data | tst.js:21:22:21:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:21:22:21:36 | req.params.data | user-provided value | +| tst.js:24:22:24:36 | req.params.data | tst.js:24:22:24:36 | req.params.data | tst.js:24:22:24:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:24:22:24:36 | req.params.data | user-provided value | +| tst.js:25:22:25:36 | req.params.data | tst.js:25:22:25:36 | req.params.data | tst.js:25:22:25:36 | req.params.data | Unsafe deserialization depends on a $@. | tst.js:25:22:25:36 | req.params.data | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-502/tst.js b/javascript/ql/test/query-tests/Security/CWE-502/tst.js index 96dfbc01fc5..e1586642357 100644 --- a/javascript/ql/test/query-tests/Security/CWE-502/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-502/tst.js @@ -4,11 +4,24 @@ var express = require('express'); var app = express(); app.post('/store/:id', function(req, res) { let data; - data = jsyaml.load(req.params.data); // NOT OK - data = jsyaml.loadAll(req.params.data); // NOT OK + data = jsyaml.load(req.params.data); // OK + data = jsyaml.loadAll(req.params.data); // OK data = jsyaml.safeLoad(req.params.data); // OK data = jsyaml.safeLoadAll(req.params.data); // OK + let unsafeConfig = { schema: jsyaml.DEFAULT_FULL_SCHEMA }; + data = jsyaml.load(req.params.data, unsafeConfig); // NOT OK + data = jsyaml.loadAll(req.params.data, unsafeConfig); // NOT OK data = jsyaml.safeLoad(req.params.data, unsafeConfig); // NOT OK data = jsyaml.safeLoadAll(req.params.data, unsafeConfig); // NOT OK + + data = jsyaml.load(req.params.data, { schema: jsyaml.DEFAULT_SCHEMA }); // OK + + data = jsyaml.load(req.params.data, { schema: jsyaml.DEFAULT_SCHEMA.extend(require('js-yaml-js-types').all) }); // NOT OK + data = jsyaml.load(req.params.data, { schema: jsyaml.DEFAULT_SCHEMA.extend(require('js-yaml-js-types').function) }); // NOT OK + data = jsyaml.load(req.params.data, { schema: jsyaml.DEFAULT_SCHEMA.extend(require('js-yaml-js-types').undefined) }); // OK + + data = jsyaml.load(req.params.data, { schema: require('js-yaml-js-types').all.extend(jsyaml.DEFAULT_SCHEMA) }); // NOT OK + data = jsyaml.load(req.params.data, { schema: require('js-yaml-js-types').function.extend(jsyaml.DEFAULT_SCHEMA) }); // NOT OK + data = jsyaml.load(req.params.data, { schema: require('js-yaml-js-types').undefined.extend(jsyaml.DEFAULT_SCHEMA) }); // OK }); From 5f011a262c47f0b9d9738f5d2c71148de6fa630a Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 12:49:24 +0200 Subject: [PATCH 20/96] JS: Change note --- .../change-notes/2023-04-26-unsafe-yaml-deserialization.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 javascript/ql/src/change-notes/2023-04-26-unsafe-yaml-deserialization.md diff --git a/javascript/ql/src/change-notes/2023-04-26-unsafe-yaml-deserialization.md b/javascript/ql/src/change-notes/2023-04-26-unsafe-yaml-deserialization.md new file mode 100644 index 00000000000..02b044ee47a --- /dev/null +++ b/javascript/ql/src/change-notes/2023-04-26-unsafe-yaml-deserialization.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* The `js/unsafe-deserialization` query no longer flags deserialization through the `js-yaml` library, except + when it is used with an unsafe schema. From 1a97e8f32903f9c7ac88f1516493831463cd65df Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 24 Apr 2023 12:29:21 +0200 Subject: [PATCH 21/96] Python: Add flow-step for arg[1] to `dict.setdefault` --- .../lib/semmle/python/frameworks/Stdlib.qll | 24 +++++++++++++++++++ .../dataflow/fieldflow/test_dict.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index e79aa270945..961b4c808d7 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -3795,6 +3795,30 @@ private module StdlibPrivate { preservesValue = true } } + + /** + * A flow summary for `dict.setdefault`. + * + * See https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault + */ + class DictSetdefaultSummary extends SummarizedCallable { + DictSetdefaultSummary() { this = "dict.setdefault" } + + override DataFlow::CallCfgNode getACall() { + result.(DataFlow::MethodCallNode).calls(_, "setdefault") + } + + override DataFlow::ArgumentNode getACallback() { + result.(DataFlow::AttrRead).getAttributeName() = "setdefault" + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + // store/read steps with dictionary content of this is modeled in DataFlowPrivate + input = "Argument[1]" and + output = "ReturnValue" and + preservesValue = true + } + } } // --------------------------------------------------------------------------- diff --git a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py index 19b60576191..1a78f703ba8 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py +++ b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py @@ -49,7 +49,7 @@ def test_dict_update(): def test_setdefault(): d = {} x = d.setdefault("key", SOURCE) - SINK(x) # $ MISSING: flow="SOURCE, l:-1 -> d.setdefault(..)" + SINK(x) # $ flow="SOURCE, l:-1 -> x" SINK(d["key"]) # $ flow="SOURCE, l:-2 -> d['key']" SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)" From 3f3964806595a99f9bd976a731be07c291226ca2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 26 Apr 2023 12:48:42 +0200 Subject: [PATCH 22/96] Python: Remove duplicated test --- .../ql/test/experimental/dataflow/fieldflow/test_dict.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py index 1a78f703ba8..c2f74b83c3d 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/test_dict.py +++ b/python/ql/test/experimental/dataflow/fieldflow/test_dict.py @@ -46,7 +46,7 @@ def test_dict_update(): SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)" @expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) -def test_setdefault(): +def test_dict_setdefault(): d = {} x = d.setdefault("key", SOURCE) SINK(x) # $ flow="SOURCE, l:-1 -> x" @@ -62,13 +62,6 @@ def test_dict_override(): d["key"] = NONSOURCE SINK_F(d["key"]) - -def test_dict_setdefault(): - d = {} - d.setdefault("key", SOURCE) - SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']" - - @expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..) def test_dict_nonstring_key(): d = {} From b178c9cfe68270764a20c09b38fc8324429ac9c2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 26 Apr 2023 13:15:08 +0200 Subject: [PATCH 23/96] Python: Accept dataflow/basic/*.expected --- .../test/experimental/dataflow/basic/callGraphSinks.expected | 1 + .../test/experimental/dataflow/basic/callGraphSources.expected | 1 + python/ql/test/experimental/dataflow/basic/global.expected | 1 + python/ql/test/experimental/dataflow/basic/globalStep.expected | 1 + python/ql/test/experimental/dataflow/basic/local.expected | 3 +++ python/ql/test/experimental/dataflow/basic/localStep.expected | 1 + .../ql/test/experimental/dataflow/basic/maximalFlows.expected | 1 + python/ql/test/experimental/dataflow/basic/sinks.expected | 2 ++ python/ql/test/experimental/dataflow/basic/sources.expected | 2 ++ 9 files changed, 13 insertions(+) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected index 0f87376ef1a..ef35d8f5039 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected @@ -1,4 +1,5 @@ | file://:0:0:0:0 | parameter position 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:19:1:19 | ControlFlowNode for x | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected index 0b4613c42de..74d546c5f2b 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected +++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected @@ -1,3 +1,4 @@ | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | +| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:4:10:4:10 | ControlFlowNode for z | | test.py:7:19:7:19 | ControlFlowNode for a | diff --git a/python/ql/test/experimental/dataflow/basic/global.expected b/python/ql/test/experimental/dataflow/basic/global.expected index 800312b07be..11696c17335 100644 --- a/python/ql/test/experimental/dataflow/basic/global.expected +++ b/python/ql/test/experimental/dataflow/basic/global.expected @@ -1,4 +1,5 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.expected b/python/ql/test/experimental/dataflow/basic/globalStep.expected index fa5b20486c2..b11ee6fe249 100644 --- a/python/ql/test/experimental/dataflow/basic/globalStep.expected +++ b/python/ql/test/experimental/dataflow/basic/globalStep.expected @@ -1,4 +1,5 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/local.expected b/python/ql/test/experimental/dataflow/basic/local.expected index 2354efea8e5..18497a00a60 100644 --- a/python/ql/test/experimental/dataflow/basic/local.expected +++ b/python/ql/test/experimental/dataflow/basic/local.expected @@ -1,8 +1,11 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | +| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b | diff --git a/python/ql/test/experimental/dataflow/basic/localStep.expected b/python/ql/test/experimental/dataflow/basic/localStep.expected index 534c31da1a6..d05e8aa3a42 100644 --- a/python/ql/test/experimental/dataflow/basic/localStep.expected +++ b/python/ql/test/experimental/dataflow/basic/localStep.expected @@ -1,4 +1,5 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected index b6f8a1730f1..b65b4b4d30a 100644 --- a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected +++ b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected @@ -1,3 +1,4 @@ +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:7:1:7:1 | GSSA Variable b | | test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z | diff --git a/python/ql/test/experimental/dataflow/basic/sinks.expected b/python/ql/test/experimental/dataflow/basic/sinks.expected index aafff76bbe2..1e516e32336 100644 --- a/python/ql/test/experimental/dataflow/basic/sinks.expected +++ b/python/ql/test/experimental/dataflow/basic/sinks.expected @@ -1,7 +1,9 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | +| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | file://:0:0:0:0 | parameter position 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | diff --git a/python/ql/test/experimental/dataflow/basic/sources.expected b/python/ql/test/experimental/dataflow/basic/sources.expected index aafff76bbe2..1e516e32336 100644 --- a/python/ql/test/experimental/dataflow/basic/sources.expected +++ b/python/ql/test/experimental/dataflow/basic/sources.expected @@ -1,7 +1,9 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | +| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | | file://:0:0:0:0 | parameter position 0 of builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | From abc1d658e064a3d9b85cfd6a95fd6d27fbca5210 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 26 Apr 2023 14:10:13 +0200 Subject: [PATCH 24/96] Python: More `.expected` accepting --- .../dataflow/tainttracking/basic/LocalTaintStep.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected index 05b64297f71..ef6f6a2929b 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected @@ -1,4 +1,5 @@ | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | +| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:3:1:3:7 | GSSA Variable tainted | test.py:4:6:4:12 | ControlFlowNode for tainted | | test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:3:1:3:7 | GSSA Variable tainted | | test.py:6:1:6:11 | ControlFlowNode for FunctionExpr | test.py:6:5:6:8 | GSSA Variable func | From cb04df49ebe24b436c294ac0ff1a20c1f1152914 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 14:12:54 +0200 Subject: [PATCH 25/96] JS: Treat Angular2 ElementRef.nativeElement as a DOM value --- javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 1dcd39a0d62..290860887a0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -547,4 +547,10 @@ module Angular2 { ) } } + + private class DomValueSources extends DOM::DomValueSource::Range { + DomValueSources() { + this = API::Node::ofType("@angular/core", "ElementRef").getMember("nativeElement").asSource() + } + } } From 4df05b4e74d8d96eb7c6a54803969f1dd646d011 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 14:29:28 +0200 Subject: [PATCH 26/96] JS: Shift line numbers in test --- .../frameworks/Angular2/source.component.ts | 3 ++- .../frameworks/Angular2/test.expected | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts index 63b981367b3..88e864dbcbf 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component,ElementRef } from "@angular/core"; import { DomSanitizer } from '@angular/platform-browser'; @Component({ @@ -9,6 +9,7 @@ export class Source { taint: string; taintedArray: string[]; safeArray: string[]; + elementRef: ElementRef; constructor(private sanitizer: DomSanitizer) { this.taint = source(); diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index de4f3bb3796..ddd6021a764 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -24,13 +24,13 @@ pipeClassRef taintFlow | inline.component.ts:15:22:15:29 | source() | sink.component.ts:28:48:28:57 | this.sink7 | | inline.component.ts:15:22:15:29 | source() | sink.component.ts:30:48:30:57 | this.sink9 | -| source.component.ts:14:22:14:29 | source() | TestPipe.ts:6:31:6:35 | value | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:22:48:22:57 | this.sink1 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink4 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:26:48:26:57 | this.sink5 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:27:48:27:57 | this.sink6 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 | -| source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x | -| source.component.ts:15:33:15:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 | +| source.component.ts:15:22:15:29 | source() | TestPipe.ts:6:31:6:35 | value | +| source.component.ts:15:22:15:29 | source() | sink.component.ts:22:48:22:57 | this.sink1 | +| source.component.ts:15:22:15:29 | source() | sink.component.ts:25:48:25:57 | this.sink4 | +| source.component.ts:15:22:15:29 | source() | sink.component.ts:26:48:26:57 | this.sink5 | +| source.component.ts:15:22:15:29 | source() | sink.component.ts:27:48:27:57 | this.sink6 | +| source.component.ts:15:22:15:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 | +| source.component.ts:15:22:15:29 | source() | source.component.ts:21:48:21:48 | x | +| source.component.ts:16:33:16:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 | testAttrSourceLocation | inline.component.ts:8:43:8:60 | [testAttr]=taint | inline.component.ts:8:55:8:59 | | From 0d74d88b7b22d46d51599f9d9f67ad39b1aae7eb Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 14:32:37 +0200 Subject: [PATCH 27/96] JS: Add new sink to test --- .../test/library-tests/frameworks/Angular2/source.component.ts | 1 + .../ql/test/library-tests/frameworks/Angular2/test.expected | 1 + 2 files changed, 2 insertions(+) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts index 88e864dbcbf..12a5efb39ec 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts @@ -19,5 +19,6 @@ export class Source { methodOnComponent(x) { this.sanitizer.bypassSecurityTrustHtml(x); + this.elementRef.nativeElement.innerHTML = x; } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index ddd6021a764..f09f0aed3b4 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -31,6 +31,7 @@ taintFlow | source.component.ts:15:22:15:29 | source() | sink.component.ts:27:48:27:57 | this.sink6 | | source.component.ts:15:22:15:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 | | source.component.ts:15:22:15:29 | source() | source.component.ts:21:48:21:48 | x | +| source.component.ts:15:22:15:29 | source() | source.component.ts:22:51:22:51 | x | | source.component.ts:16:33:16:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 | testAttrSourceLocation | inline.component.ts:8:43:8:60 | [testAttr]=taint | inline.component.ts:8:55:8:59 | | From 1f228a049f8cabef5c5856d43e3be5e3a372fc36 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 14:54:38 +0200 Subject: [PATCH 28/96] JS: Add test for iterating over DOM collections --- javascript/ql/test/library-tests/DOM/Customizations.expected | 3 +++ javascript/ql/test/library-tests/DOM/querySelectorAll.js | 5 +++++ 2 files changed, 8 insertions(+) create mode 100644 javascript/ql/test/library-tests/DOM/querySelectorAll.js diff --git a/javascript/ql/test/library-tests/DOM/Customizations.expected b/javascript/ql/test/library-tests/DOM/Customizations.expected index 58602b221c7..6ae76bda1ab 100644 --- a/javascript/ql/test/library-tests/DOM/Customizations.expected +++ b/javascript/ql/test/library-tests/DOM/Customizations.expected @@ -3,6 +3,7 @@ test_documentRef | event-handler-receiver.js:1:1:1:8 | document | | event-handler-receiver.js:5:1:5:8 | document | | nameditems.js:1:1:1:8 | document | +| querySelectorAll.js:2:5:2:12 | document | test_locationRef | customization.js:3:3:3:14 | doc.location | test_domValueRef @@ -20,5 +21,7 @@ test_domValueRef | nameditems.js:1:1:1:23 | documen ... entById | | nameditems.js:1:1:1:30 | documen ... ('foo') | | nameditems.js:1:1:2:19 | documen ... em('x') | +| querySelectorAll.js:2:5:2:29 | documen ... ctorAll | +| querySelectorAll.js:2:5:2:36 | documen ... ('foo') | | tst.js:49:3:49:8 | window | | tst.js:50:3:50:8 | window | diff --git a/javascript/ql/test/library-tests/DOM/querySelectorAll.js b/javascript/ql/test/library-tests/DOM/querySelectorAll.js new file mode 100644 index 00000000000..22292ddfefd --- /dev/null +++ b/javascript/ql/test/library-tests/DOM/querySelectorAll.js @@ -0,0 +1,5 @@ +(function() { + document.querySelectorAll('foo').forEach(elm => { + elm.innerHTML = 'hey'; + }); +}); From cf1e87de9e2b512e822f4bfdb68bd7bf58db8bf9 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Apr 2023 14:55:34 +0200 Subject: [PATCH 29/96] JS: Track DOM elements out of collections --- javascript/ql/lib/semmle/javascript/DOM.qll | 3 +++ javascript/ql/test/library-tests/DOM/Customizations.expected | 1 + 2 files changed, 4 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index f06f43d5976..3dbe734b0fb 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -421,6 +421,9 @@ module DOM { t.startInProp("target") and result = domEventSource() or + t.startInProp(DataFlow::PseudoProperties::arrayElement()) and + result = domElementCollection() + or exists(DataFlow::TypeTracker t2 | result = domValueRef(t2).track(t2, t)) } diff --git a/javascript/ql/test/library-tests/DOM/Customizations.expected b/javascript/ql/test/library-tests/DOM/Customizations.expected index 6ae76bda1ab..3fc5570c743 100644 --- a/javascript/ql/test/library-tests/DOM/Customizations.expected +++ b/javascript/ql/test/library-tests/DOM/Customizations.expected @@ -23,5 +23,6 @@ test_domValueRef | nameditems.js:1:1:2:19 | documen ... em('x') | | querySelectorAll.js:2:5:2:29 | documen ... ctorAll | | querySelectorAll.js:2:5:2:36 | documen ... ('foo') | +| querySelectorAll.js:2:46:2:48 | elm | | tst.js:49:3:49:8 | window | | tst.js:50:3:50:8 | window | From ce1c4b88d86455c14d31d935a37cf723879281c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:20:13 +0200 Subject: [PATCH 30/96] Swift: rename Function hierarchy in schema.py --- swift/schema.py | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/swift/schema.py b/swift/schema.py index c7eac050077..8fc0941e171 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -141,7 +141,7 @@ class ValueDecl(Decl): interface_type: Type class AbstractStorageDecl(ValueDecl): - accessor_decls: list["AccessorDecl"] | child + accessors: list["Accessor"] | child class VarDecl(AbstractStorageDecl): """ @@ -234,7 +234,8 @@ class Callable(Element): body: optional["BraceStmt"] | child | desc("The body is absent within protocol declarations.") captures: list["CapturedDecl"] | child -class AbstractFunctionDecl(GenericContext, ValueDecl, Callable): +@group("decl") +class Function(GenericContext, ValueDecl, Callable): pass class EnumElementDecl(ValueDecl): @@ -257,13 +258,17 @@ class TypeDecl(ValueDecl): class AbstractTypeParamDecl(TypeDecl): pass -class ConstructorDecl(AbstractFunctionDecl): +@group("decl") +class Initializer(Function): pass -class DestructorDecl(AbstractFunctionDecl): +@group("decl") +class Deinitializer(Function): pass -class FuncDecl(AbstractFunctionDecl): +@ql.internal +@group("decl") +class AccessorOrNamedFunction(Function): pass class GenericTypeDecl(GenericContext, TypeDecl): @@ -280,7 +285,8 @@ class SubscriptDecl(AbstractStorageDecl, GenericContext): element_type: Type element_type: Type -class AccessorDecl(FuncDecl): +@group("decl") +class Accessor(AccessorOrNamedFunction): is_getter: predicate | doc('this accessor is a getter') is_setter: predicate | doc('this accessor is a setter') is_will_set: predicate | doc('this accessor is a `willSet`, called before the property is set') @@ -293,7 +299,8 @@ class AccessorDecl(FuncDecl): class AssociatedTypeDecl(AbstractTypeParamDecl): pass -class ConcreteFuncDecl(FuncDecl): +@group("decl") +class NamedFunction(AccessorOrNamedFunction): pass class ConcreteVarDecl(VarDecl): @@ -354,7 +361,7 @@ class Argument(Locatable): label: string expr: Expr | child -class AbstractClosureExpr(Expr, Callable): +class ClosureExpr(Expr, Callable): pass class AnyTryExpr(Expr): @@ -384,7 +391,7 @@ class CapturedDecl(Decl): class CaptureListExpr(Expr): binding_decls: list[PatternBindingDecl] | child - closure_body: "ClosureExpr" | child + closure_body: "ExplicitClosureExpr" | child class CollectionExpr(Expr): pass @@ -482,7 +489,7 @@ class KeyPathExpr(Expr): root: optional["TypeRepr"] | child components: list[KeyPathComponent] | child -class LazyInitializerExpr(Expr): +class LazyInitializationExpr(Expr): sub_expr: Expr | child class LiteralExpr(Expr): @@ -500,7 +507,7 @@ class MakeTemporarilyEscapableExpr(Expr): @qltest.skip class ObjCSelectorExpr(Expr): sub_expr: Expr | child - method: AbstractFunctionDecl + method: Function class OneWayExpr(Expr): sub_expr: Expr | child @@ -516,8 +523,8 @@ class OpenExistentialExpr(Expr): class OptionalEvaluationExpr(Expr): sub_expr: Expr | child -class OtherConstructorDeclRefExpr(Expr): - constructor_decl: ConstructorDecl +class OtherInitializerRefExpr(Expr): + initializer: Initializer class PropertyWrapperValuePlaceholderExpr(Expr): """ @@ -527,7 +534,7 @@ class PropertyWrapperValuePlaceholderExpr(Expr): wrapped_value: optional[Expr] placeholder: OpaqueValueExpr -class RebindSelfInConstructorExpr(Expr): +class RebindSelfInInitializerExpr(Expr): sub_expr: Expr | child self: VarDecl @@ -579,7 +586,7 @@ class ArrayExpr(CollectionExpr): class ArrayToPointerExpr(ImplicitConversionExpr): pass -class AutoClosureExpr(AbstractClosureExpr): +class AutoClosureExpr(ClosureExpr): pass class AwaitExpr(IdentityExpr): @@ -608,7 +615,7 @@ class CheckedCastExpr(ExplicitCastExpr): class ClassMetatypeToObjectExpr(ImplicitConversionExpr): pass -class ClosureExpr(AbstractClosureExpr): +class ExplicitClosureExpr(ClosureExpr): pass class CoerceExpr(ExplicitCastExpr): @@ -776,9 +783,11 @@ class BooleanLiteralExpr(BuiltinLiteralExpr): class ConditionalCheckedCastExpr(CheckedCastExpr): pass -class ConstructorRefCallExpr(SelfApplyExpr): +@ql.internal +class InitializerRefCallExpr(SelfApplyExpr): pass +@ql.internal class DotSyntaxCallExpr(SelfApplyExpr): pass From 90ad36ed6c878151f02571951d4eae7791a52bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:21:04 +0200 Subject: [PATCH 31/96] Swift: update extractor --- swift/extractor/infra/SwiftTagTraits.h | 24 +++++++++---------- .../extractor/translators/DeclTranslator.cpp | 23 +++++++++--------- swift/extractor/translators/DeclTranslator.h | 11 ++++----- .../extractor/translators/ExprTranslator.cpp | 20 ++++++++-------- swift/extractor/translators/ExprTranslator.h | 14 +++++------ 5 files changed, 45 insertions(+), 47 deletions(-) diff --git a/swift/extractor/infra/SwiftTagTraits.h b/swift/extractor/infra/SwiftTagTraits.h index f8c66512f9c..3ba1b25bfcc 100644 --- a/swift/extractor/infra/SwiftTagTraits.h +++ b/swift/extractor/infra/SwiftTagTraits.h @@ -77,7 +77,7 @@ MAP(swift::Expr, ExprTag) MAP(swift::DeclRefExpr, DeclRefExprTag) MAP(swift::SuperRefExpr, SuperRefExprTag) MAP(swift::TypeExpr, TypeExprTag) - MAP(swift::OtherConstructorDeclRefExpr, OtherConstructorDeclRefExprTag) + MAP(swift::OtherConstructorDeclRefExpr, OtherInitializerRefExprTag) MAP(swift::DotSyntaxBaseIgnoredExpr, DotSyntaxBaseIgnoredExprTag) MAP(swift::OverloadSetRefExpr, OverloadedDeclRefExprTag) // collapsed with its only derived class OverloadedDeclRefExpr MAP(swift::OverloadedDeclRefExpr, OverloadedDeclRefExprTag) @@ -108,13 +108,13 @@ MAP(swift::Expr, ExprTag) MAP(swift::KeyPathApplicationExpr, KeyPathApplicationExprTag) MAP(swift::TupleElementExpr, TupleElementExprTag) MAP(swift::CaptureListExpr, CaptureListExprTag) - MAP(swift::AbstractClosureExpr, AbstractClosureExprTag) - MAP(swift::ClosureExpr, ClosureExprTag) + MAP(swift::AbstractClosureExpr, ClosureExprTag) + MAP(swift::ClosureExpr, ExplicitClosureExprTag) MAP(swift::AutoClosureExpr, AutoClosureExprTag) MAP(swift::InOutExpr, InOutExprTag) MAP(swift::VarargExpansionExpr, VarargExpansionExprTag) MAP(swift::DynamicTypeExpr, DynamicTypeExprTag) - MAP(swift::RebindSelfInConstructorExpr, RebindSelfInConstructorExprTag) + MAP(swift::RebindSelfInConstructorExpr, RebindSelfInInitializerExprTag) MAP(swift::OpaqueValueExpr, OpaqueValueExprTag) MAP(swift::PropertyWrapperValuePlaceholderExpr, PropertyWrapperValuePlaceholderExprTag) MAP(swift::AppliedPropertyWrapperExpr, AppliedPropertyWrapperExprTag) @@ -131,7 +131,7 @@ MAP(swift::Expr, ExprTag) MAP(swift::BinaryExpr, BinaryExprTag) MAP(swift::SelfApplyExpr, SelfApplyExprTag) MAP(swift::DotSyntaxCallExpr, DotSyntaxCallExprTag) - MAP(swift::ConstructorRefCallExpr, ConstructorRefCallExprTag) + MAP(swift::ConstructorRefCallExpr, InitializerRefCallExprTag) MAP(swift::ImplicitConversionExpr, ImplicitConversionExprTag) MAP(swift::LoadExpr, LoadExprTag) MAP(swift::DestructureTupleExpr, DestructureTupleExprTag) @@ -178,7 +178,7 @@ MAP(swift::Expr, ExprTag) MAP(swift::AssignExpr, AssignExprTag) MAP(swift::CodeCompletionExpr, void) // only generated for code editing MAP(swift::UnresolvedPatternExpr, UnresolvedPatternExprTag) - MAP(swift::LazyInitializerExpr, LazyInitializerExprTag) + MAP(swift::LazyInitializerExpr, LazyInitializationExprTag) MAP(swift::EditorPlaceholderExpr, void) // only generated for code editing MAP(swift::ObjCSelectorExpr, ObjCSelectorExprTag) MAP(swift::KeyPathExpr, KeyPathExprTag) @@ -207,12 +207,12 @@ MAP(swift::Decl, DeclTag) MAP_CONCRETE(swift::VarDecl, ConcreteVarDeclTag) MAP(swift::ParamDecl, ParamDeclTag) MAP(swift::SubscriptDecl, SubscriptDeclTag) - MAP(swift::AbstractFunctionDecl, AbstractFunctionDeclTag) - MAP(swift::ConstructorDecl, ConstructorDeclTag) - MAP(swift::DestructorDecl, DestructorDeclTag) - MAP(swift::FuncDecl, FuncDeclTag) - MAP_CONCRETE(swift::FuncDecl, ConcreteFuncDeclTag) - MAP(swift::AccessorDecl, AccessorDeclTag) + MAP(swift::AbstractFunctionDecl, FunctionTag) + MAP(swift::ConstructorDecl, InitializerTag) + MAP(swift::DestructorDecl, DeinitializerTag) + MAP(swift::FuncDecl, AccessorOrNamedFunctionTag) + MAP_CONCRETE(swift::FuncDecl, NamedFunctionTag) + MAP(swift::AccessorDecl, AccessorTag) MAP(swift::EnumElementDecl, EnumElementDeclTag) MAP(swift::ExtensionDecl, ExtensionDeclTag) MAP(swift::TopLevelCodeDecl, TopLevelCodeDeclTag) diff --git a/swift/extractor/translators/DeclTranslator.cpp b/swift/extractor/translators/DeclTranslator.cpp index a0cd6e4ff34..a09b3e059ec 100644 --- a/swift/extractor/translators/DeclTranslator.cpp +++ b/swift/extractor/translators/DeclTranslator.cpp @@ -24,22 +24,21 @@ std::string constructName(const swift::DeclName& declName) { } } // namespace -codeql::ConcreteFuncDecl DeclTranslator::translateFuncDecl(const swift::FuncDecl& decl) { +codeql::NamedFunction DeclTranslator::translateFuncDecl(const swift::FuncDecl& decl) { auto entry = createEntry(decl); - fillAbstractFunctionDecl(decl, entry); + fillFunction(decl, entry); return entry; } -codeql::ConstructorDecl DeclTranslator::translateConstructorDecl( - const swift::ConstructorDecl& decl) { +codeql::Initializer DeclTranslator::translateConstructorDecl(const swift::ConstructorDecl& decl) { auto entry = createEntry(decl); - fillAbstractFunctionDecl(decl, entry); + fillFunction(decl, entry); return entry; } -codeql::DestructorDecl DeclTranslator::translateDestructorDecl(const swift::DestructorDecl& decl) { +codeql::Deinitializer DeclTranslator::translateDestructorDecl(const swift::DestructorDecl& decl) { auto entry = createEntry(decl); - fillAbstractFunctionDecl(decl, entry); + fillFunction(decl, entry); return entry; } @@ -173,7 +172,7 @@ codeql::TypeAliasDecl DeclTranslator::translateTypeAliasDecl(const swift::TypeAl return entry; } -codeql::AccessorDecl DeclTranslator::translateAccessorDecl(const swift::AccessorDecl& decl) { +codeql::Accessor DeclTranslator::translateAccessorDecl(const swift::AccessorDecl& decl) { auto entry = createEntry(decl); switch (decl.getAccessorKind()) { case swift::AccessorKind::Get: @@ -201,7 +200,7 @@ codeql::AccessorDecl DeclTranslator::translateAccessorDecl(const swift::Accessor entry.is_unsafe_mutable_address = true; break; } - fillAbstractFunctionDecl(decl, entry); + fillFunction(decl, entry); return entry; } @@ -251,8 +250,8 @@ codeql::ModuleDecl DeclTranslator::translateModuleDecl(const swift::ModuleDecl& return entry; } -void DeclTranslator::fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl, - codeql::AbstractFunctionDecl& entry) { +void DeclTranslator::fillFunction(const swift::AbstractFunctionDecl& decl, + codeql::Function& entry) { assert(decl.hasParameterList() && "Expect functions to have a parameter list"); entry.name = !decl.hasName() ? "(unnamed function decl)" : constructName(decl.getName()); entry.body = dispatcher.fetchOptionalLabel(decl.getBody()); @@ -328,7 +327,7 @@ void DeclTranslator::fillValueDecl(const swift::ValueDecl& decl, codeql::ValueDe void DeclTranslator::fillAbstractStorageDecl(const swift::AbstractStorageDecl& decl, codeql::AbstractStorageDecl& entry) { - entry.accessor_decls = dispatcher.fetchRepeatedLabels(decl.getAllAccessors()); + entry.accessors = dispatcher.fetchRepeatedLabels(decl.getAllAccessors()); fillValueDecl(decl, entry); } diff --git a/swift/extractor/translators/DeclTranslator.h b/swift/extractor/translators/DeclTranslator.h index 6abadd03188..13b606c7b02 100644 --- a/swift/extractor/translators/DeclTranslator.h +++ b/swift/extractor/translators/DeclTranslator.h @@ -16,9 +16,9 @@ class DeclTranslator : public AstTranslatorBase { public: using AstTranslatorBase::AstTranslatorBase; - codeql::ConcreteFuncDecl translateFuncDecl(const swift::FuncDecl& decl); - codeql::ConstructorDecl translateConstructorDecl(const swift::ConstructorDecl& decl); - codeql::DestructorDecl translateDestructorDecl(const swift::DestructorDecl& decl); + codeql::NamedFunction translateFuncDecl(const swift::FuncDecl& decl); + codeql::Initializer translateConstructorDecl(const swift::ConstructorDecl& decl); + codeql::Deinitializer translateDestructorDecl(const swift::DestructorDecl& decl); codeql::PrefixOperatorDecl translatePrefixOperatorDecl(const swift::PrefixOperatorDecl& decl); codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl); codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl); @@ -37,7 +37,7 @@ class DeclTranslator : public AstTranslatorBase { const swift::GenericTypeParamDecl& decl); codeql::AssociatedTypeDecl translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl); codeql::TypeAliasDecl translateTypeAliasDecl(const swift::TypeAliasDecl& decl); - codeql::AccessorDecl translateAccessorDecl(const swift::AccessorDecl& decl); + codeql::Accessor translateAccessorDecl(const swift::AccessorDecl& decl); codeql::SubscriptDecl translateSubscriptDecl(const swift::SubscriptDecl& decl); codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl); codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl); @@ -49,8 +49,7 @@ class DeclTranslator : public AstTranslatorBase { codeql::CapturedDecl translateCapturedValue(const swift::CapturedValue& capture); private: - void fillAbstractFunctionDecl(const swift::AbstractFunctionDecl& decl, - codeql::AbstractFunctionDecl& entry); + void fillFunction(const swift::AbstractFunctionDecl& decl, codeql::Function& entry); void fillOperatorDecl(const swift::OperatorDecl& decl, codeql::OperatorDecl& entry); void fillTypeDecl(const swift::TypeDecl& decl, codeql::TypeDecl& entry); void fillIterableDeclContext(const swift::IterableDeclContext& decl, codeql::Decl& entry); diff --git a/swift/extractor/translators/ExprTranslator.cpp b/swift/extractor/translators/ExprTranslator.cpp index 998d3b2ba65..5fc5841adb6 100644 --- a/swift/extractor/translators/ExprTranslator.cpp +++ b/swift/extractor/translators/ExprTranslator.cpp @@ -211,7 +211,7 @@ codeql::OptionalEvaluationExpr ExprTranslator::translateOptionalEvaluationExpr( return entry; } -codeql::RebindSelfInConstructorExpr ExprTranslator::translateRebindSelfInConstructorExpr( +codeql::RebindSelfInInitializerExpr ExprTranslator::translateRebindSelfInConstructorExpr( const swift::RebindSelfInConstructorExpr& expr) { auto entry = createExprEntry(expr); entry.sub_expr = dispatcher.fetchLabel(expr.getSubExpr()); @@ -300,7 +300,7 @@ codeql::OptionalTryExpr ExprTranslator::translateOptionalTryExpr( return entry; } -codeql::ConstructorRefCallExpr ExprTranslator::translateConstructorRefCallExpr( +codeql::InitializerRefCallExpr ExprTranslator::translateConstructorRefCallExpr( const swift::ConstructorRefCallExpr& expr) { auto entry = createExprEntry(expr); fillSelfApplyExpr(expr, entry); @@ -313,16 +313,16 @@ codeql::DiscardAssignmentExpr ExprTranslator::translateDiscardAssignmentExpr( return entry; } -codeql::ClosureExpr ExprTranslator::translateClosureExpr(const swift::ClosureExpr& expr) { +codeql::ExplicitClosureExpr ExprTranslator::translateClosureExpr(const swift::ClosureExpr& expr) { auto entry = createExprEntry(expr); - fillAbstractClosureExpr(expr, entry); + fillClosureExpr(expr, entry); return entry; } codeql::AutoClosureExpr ExprTranslator::translateAutoClosureExpr( const swift::AutoClosureExpr& expr) { auto entry = createExprEntry(expr); - fillAbstractClosureExpr(expr, entry); + fillClosureExpr(expr, entry); return entry; } @@ -393,7 +393,7 @@ codeql::KeyPathExpr ExprTranslator::translateKeyPathExpr(const swift::KeyPathExp return entry; } -codeql::LazyInitializerExpr ExprTranslator::translateLazyInitializerExpr( +codeql::LazyInitializationExpr ExprTranslator::translateLazyInitializerExpr( const swift::LazyInitializerExpr& expr) { auto entry = createExprEntry(expr); entry.sub_expr = dispatcher.fetchLabel(expr.getSubExpr()); @@ -427,10 +427,10 @@ codeql::KeyPathApplicationExpr ExprTranslator::translateKeyPathApplicationExpr( return entry; } -codeql::OtherConstructorDeclRefExpr ExprTranslator::translateOtherConstructorDeclRefExpr( +codeql::OtherInitializerRefExpr ExprTranslator::translateOtherConstructorDeclRefExpr( const swift::OtherConstructorDeclRefExpr& expr) { auto entry = createExprEntry(expr); - entry.constructor_decl = dispatcher.fetchLabel(expr.getDecl()); + entry.initializer = dispatcher.fetchLabel(expr.getDecl()); return entry; } @@ -472,8 +472,8 @@ codeql::ErrorExpr ExprTranslator::translateErrorExpr(const swift::ErrorExpr& exp return entry; } -void ExprTranslator::fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr, - codeql::AbstractClosureExpr& entry) { +void ExprTranslator::fillClosureExpr(const swift::AbstractClosureExpr& expr, + codeql::ClosureExpr& entry) { assert(expr.getParameters() && "AbstractClosureExpr has getParameters()"); entry.params = dispatcher.fetchRepeatedLabels(*expr.getParameters()); entry.body = dispatcher.fetchLabel(expr.getBody()); diff --git a/swift/extractor/translators/ExprTranslator.h b/swift/extractor/translators/ExprTranslator.h index 335329334d4..fe0dbb59617 100644 --- a/swift/extractor/translators/ExprTranslator.h +++ b/swift/extractor/translators/ExprTranslator.h @@ -39,7 +39,7 @@ class ExprTranslator : public AstTranslatorBase { codeql::OpenExistentialExpr translateOpenExistentialExpr(const swift::OpenExistentialExpr& expr); codeql::OptionalEvaluationExpr translateOptionalEvaluationExpr( const swift::OptionalEvaluationExpr& expr); - codeql::RebindSelfInConstructorExpr translateRebindSelfInConstructorExpr( + codeql::RebindSelfInInitializerExpr translateRebindSelfInConstructorExpr( const swift::RebindSelfInConstructorExpr& expr); codeql::SuperRefExpr translateSuperRefExpr(const swift::SuperRefExpr& expr); codeql::DotSyntaxCallExpr translateDotSyntaxCallExpr(const swift::DotSyntaxCallExpr& expr); @@ -69,11 +69,11 @@ class ExprTranslator : public AstTranslatorBase { codeql::TryExpr translateTryExpr(const swift::TryExpr& expr); codeql::ForceTryExpr translateForceTryExpr(const swift::ForceTryExpr& expr); codeql::OptionalTryExpr translateOptionalTryExpr(const swift::OptionalTryExpr& expr); - codeql::ConstructorRefCallExpr translateConstructorRefCallExpr( + codeql::InitializerRefCallExpr translateConstructorRefCallExpr( const swift::ConstructorRefCallExpr& expr); codeql::DiscardAssignmentExpr translateDiscardAssignmentExpr( const swift::DiscardAssignmentExpr& expr); - codeql::ClosureExpr translateClosureExpr(const swift::ClosureExpr& expr); + codeql::ExplicitClosureExpr translateClosureExpr(const swift::ClosureExpr& expr); codeql::AutoClosureExpr translateAutoClosureExpr(const swift::AutoClosureExpr& expr); codeql::CoerceExpr translateCoerceExpr(const swift::CoerceExpr& expr); codeql::ConditionalCheckedCastExpr translateConditionalCheckedCastExpr( @@ -85,13 +85,14 @@ class ExprTranslator : public AstTranslatorBase { codeql::DictionaryExpr translateDictionaryExpr(const swift::DictionaryExpr& expr); codeql::MemberRefExpr translateMemberRefExpr(const swift::MemberRefExpr& expr); codeql::KeyPathExpr translateKeyPathExpr(const swift::KeyPathExpr& expr); - codeql::LazyInitializerExpr translateLazyInitializerExpr(const swift::LazyInitializerExpr& expr); + codeql::LazyInitializationExpr translateLazyInitializerExpr( + const swift::LazyInitializerExpr& expr); codeql::ForceValueExpr translateForceValueExpr(const swift::ForceValueExpr& expr); codeql::IfExpr translateIfExpr(const swift::IfExpr& expr); codeql::KeyPathDotExpr translateKeyPathDotExpr(const swift::KeyPathDotExpr& expr); codeql::KeyPathApplicationExpr translateKeyPathApplicationExpr( const swift::KeyPathApplicationExpr& expr); - codeql::OtherConstructorDeclRefExpr translateOtherConstructorDeclRefExpr( + codeql::OtherInitializerRefExpr translateOtherConstructorDeclRefExpr( const swift::OtherConstructorDeclRefExpr& expr); codeql::UnresolvedDeclRefExpr translateUnresolvedDeclRefExpr( const swift::UnresolvedDeclRefExpr& expr); @@ -118,8 +119,7 @@ class ExprTranslator : public AstTranslatorBase { codeql::RegexLiteralExpr translateRegexLiteralExpr(const swift::RegexLiteralExpr& expr); private: - void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr, - codeql::AbstractClosureExpr& entry); + void fillClosureExpr(const swift::AbstractClosureExpr& expr, codeql::ClosureExpr& entry); TrapLabel emitArgument(const swift::Argument& arg); TrapLabel emitKeyPathComponent(const swift::KeyPathExpr::Component& expr); void fillExplicitCastExpr(const swift::ExplicitCastExpr& expr, codeql::ExplicitCastExpr& entry); From 2d9295a5a4780e4f53f4bc5ec29dc7a386033dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:34:23 +0200 Subject: [PATCH 32/96] Swift: [generated] library code changes --- swift/ql/.generated.list | 126 +++--- swift/ql/lib/codeql/swift/elements.qll | 21 +- .../elements/decl/AbstractFunctionDecl.qll | 16 - .../AccessorConstructor.qll} | 2 +- .../swift/elements/decl/AccessorDecl.qll | 40 -- .../elements/decl/AccessorOrNamedFunction.qll | 4 + .../swift/elements/decl/ConcreteFuncDecl.qll | 4 - .../swift/elements/decl/ConstructorDecl.qll | 17 - ...uctor.qll => DeinitializerConstructor.qll} | 2 +- .../swift/elements/decl/DestructorDecl.qll | 9 - .../codeql/swift/elements/decl/FuncDecl.qll | 4 - ...tructor.qll => InitializerConstructor.qll} | 2 +- .../swift/elements/decl/NamedFunction.qll | 4 + ...uctor.qll => NamedFunctionConstructor.qll} | 2 +- .../elements/expr/AbstractClosureExpr.qll | 4 - .../elements/expr/ConstructorRefCallExpr.qll | 4 - .../elements/expr/ExplicitClosureExpr.qll | 4 + ...qll => ExplicitClosureExprConstructor.qll} | 2 +- .../elements/expr/InitializerRefCallExpr.qll | 4 + ... => InitializerRefCallExprConstructor.qll} | 2 +- .../LazyInitializationExprConstructor.qll} | 2 +- .../elements/expr/LazyInitializerExpr.qll | 5 - .../expr/OtherConstructorDeclRefExpr.qll | 5 - ...OtherConstructorDeclRefExprConstructor.qll | 4 - .../OtherInitializerRefExprConstructor.qll | 4 + .../expr/RebindSelfInConstructorExpr.qll | 5 - ...RebindSelfInConstructorExprConstructor.qll | 4 - ...RebindSelfInInitializerExprConstructor.qll | 4 + .../codeql/swift/generated/ParentChild.qll | 308 ++++++------- swift/ql/lib/codeql/swift/generated/Raw.qll | 143 +++--- swift/ql/lib/codeql/swift/generated/Synth.qll | 427 +++++++++--------- .../swift/generated/SynthConstructors.qll | 18 +- .../generated/decl/AbstractStorageDecl.qll | 24 +- .../decl/{AccessorDecl.qll => Accessor.qll} | 22 +- .../decl/AccessorOrNamedFunction.qll | 11 + .../swift/generated/decl/ConcreteFuncDecl.qll | 10 - .../swift/generated/decl/ConstructorDecl.qll | 10 - .../swift/generated/decl/Deinitializer.qll | 10 + .../swift/generated/decl/DestructorDecl.qll | 10 - .../codeql/swift/generated/decl/FuncDecl.qll | 8 - ...{AbstractFunctionDecl.qll => Function.qll} | 4 +- .../swift/generated/decl/Initializer.qll | 10 + .../swift/generated/decl/NamedFunction.qll | 10 + .../generated/expr/AbstractClosureExpr.qll | 9 - .../swift/generated/expr/AutoClosureExpr.qll | 4 +- .../swift/generated/expr/CaptureListExpr.qll | 8 +- .../swift/generated/expr/ClosureExpr.qll | 7 +- .../generated/expr/DotSyntaxCallExpr.qll | 3 + .../generated/expr/ExplicitClosureExpr.qll | 10 + ...allExpr.qll => InitializerRefCallExpr.qll} | 7 +- ...zerExpr.qll => LazyInitializationExpr.qll} | 12 +- .../swift/generated/expr/ObjCSelectorExpr.qll | 8 +- .../expr/OtherConstructorDeclRefExpr.qll | 29 -- .../expr/OtherInitializerRefExpr.qll | 29 ++ ...pr.qll => RebindSelfInInitializerExpr.qll} | 20 +- swift/ql/lib/swift.dbscheme | 186 ++++---- swift/ql/lib/swift.qll | 2 +- 57 files changed, 786 insertions(+), 879 deletions(-) delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll rename swift/ql/lib/codeql/swift/elements/{expr/ClosureExprConstructor.qll => decl/AccessorConstructor.qll} (67%) delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll create mode 100644 swift/ql/lib/codeql/swift/elements/decl/AccessorOrNamedFunction.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll rename swift/ql/lib/codeql/swift/elements/decl/{DestructorDeclConstructor.qll => DeinitializerConstructor.qll} (65%) delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/decl/FuncDecl.qll rename swift/ql/lib/codeql/swift/elements/decl/{AccessorDeclConstructor.qll => InitializerConstructor.qll} (66%) create mode 100644 swift/ql/lib/codeql/swift/elements/decl/NamedFunction.qll rename swift/ql/lib/codeql/swift/elements/decl/{ConstructorDeclConstructor.qll => NamedFunctionConstructor.qll} (64%) delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll rename swift/ql/lib/codeql/swift/elements/expr/{LazyInitializerExprConstructor.qll => ExplicitClosureExprConstructor.qll} (69%) create mode 100644 swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExpr.qll rename swift/ql/lib/codeql/swift/elements/expr/{ConstructorRefCallExprConstructor.qll => InitializerRefCallExprConstructor.qll} (50%) rename swift/ql/lib/codeql/swift/elements/{decl/ConcreteFuncDeclConstructor.qll => expr/LazyInitializationExprConstructor.qll} (60%) delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExprConstructor.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll delete mode 100644 swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExprConstructor.qll rename swift/ql/lib/codeql/swift/generated/decl/{AccessorDecl.qll => Accessor.qll} (50%) create mode 100644 swift/ql/lib/codeql/swift/generated/decl/AccessorOrNamedFunction.qll delete mode 100644 swift/ql/lib/codeql/swift/generated/decl/ConcreteFuncDecl.qll delete mode 100644 swift/ql/lib/codeql/swift/generated/decl/ConstructorDecl.qll create mode 100644 swift/ql/lib/codeql/swift/generated/decl/Deinitializer.qll delete mode 100644 swift/ql/lib/codeql/swift/generated/decl/DestructorDecl.qll delete mode 100644 swift/ql/lib/codeql/swift/generated/decl/FuncDecl.qll rename swift/ql/lib/codeql/swift/generated/decl/{AbstractFunctionDecl.qll => Function.qll} (70%) create mode 100644 swift/ql/lib/codeql/swift/generated/decl/Initializer.qll create mode 100644 swift/ql/lib/codeql/swift/generated/decl/NamedFunction.qll delete mode 100644 swift/ql/lib/codeql/swift/generated/expr/AbstractClosureExpr.qll create mode 100644 swift/ql/lib/codeql/swift/generated/expr/ExplicitClosureExpr.qll rename swift/ql/lib/codeql/swift/generated/expr/{ConstructorRefCallExpr.qll => InitializerRefCallExpr.qll} (58%) rename swift/ql/lib/codeql/swift/generated/expr/{LazyInitializerExpr.qll => LazyInitializationExpr.qll} (62%) delete mode 100644 swift/ql/lib/codeql/swift/generated/expr/OtherConstructorDeclRefExpr.qll create mode 100644 swift/ql/lib/codeql/swift/generated/expr/OtherInitializerRefExpr.qll rename swift/ql/lib/codeql/swift/generated/expr/{RebindSelfInConstructorExpr.qll => RebindSelfInInitializerExpr.qll} (62%) diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index d25c1414e89..5ecfe47f3e2 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -13,24 +13,21 @@ ql/lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll ce9c ql/lib/codeql/swift/elements/UnspecifiedElementConstructor.qll 0d179f8189f6268916f88c78a2665f8d4e78dc71e71b6229354677e915ac505d e8f5c313b7d8b0e93cee84151a5f080013d2ca502f3facbbde4cdb0889bc7f8e ql/lib/codeql/swift/elements/decl/AbstractStorageDecl.qll 5cfb9920263784224359ebd60a67ec0b46a7ea60d550d782eb1283d968386a66 74a74330a953d16ce1cc19b2dbabdf8c8ff0fc3d250d101b8108a6597844e179 ql/lib/codeql/swift/elements/decl/AbstractTypeParamDecl.qll 1847039787c20c187f2df25ea15d645d7225e1f1fd2ca543f19927fe3161fd09 737ad9c857c079605e84dc7ebaecbafa86fe129283756b98e6e574ac9e24c22c -ql/lib/codeql/swift/elements/decl/AccessorDeclConstructor.qll 08376434fd14a2b07280e931d3e22d3eafd2063d745f7c78cad0f9fd7e6156ba 6f74d15a88433953998a07eb2131841679a88cb13efb0569ed9b5502c4a2e362 +ql/lib/codeql/swift/elements/decl/AccessorConstructor.qll 1f71e110357f3e0657b4fcad27b3d1cc1f0c4615112574329f6ab1a972f9a460 61e4eacf9a909a2b6c3934f273819ae57434456dc8e83692c89d3f89ffc1fea7 +ql/lib/codeql/swift/elements/decl/AccessorOrNamedFunction.qll fa59f6554532ef41ab90144c4f02d52e473192f5e902086f28189c148f149af4 8995cc4994c78a2e13ab3aa5fb03ca80edb96a41049ad714ebb9508a5245d179 ql/lib/codeql/swift/elements/decl/AssociatedTypeDecl.qll 2f6f634fe6e3b69f1925aff0d216680962a3aaa3205bf3a89e2b66394be48f8e e81dc740623b4e2c75f83104acaa3d2b6cc6d001dd36a8520c381e0de10e15c4 ql/lib/codeql/swift/elements/decl/AssociatedTypeDeclConstructor.qll ec9007ea072ff22c367f40da69db2f0a8463bb411bbfd33e2d6c8b489a496027 631f688a8410ddcfbaa575fa2f8ffcdbc1b51ee37639b337c804ca1d5af56e0c ql/lib/codeql/swift/elements/decl/CapturedDeclConstructor.qll 4a33802b047de8d52778c262329f17b88de79c2b3162ebfa3d2b1d40dbf97041 0ed1c94469236252cf81e014138a6b2e6478e3b194512ba36e2a43e03e46cc4a ql/lib/codeql/swift/elements/decl/ClassDecl.qll 40dd7d0d66217023c8f5695eac862b38428d8f2431635f62a65b336c3cc0e9bb ac681bdc1770a823ea529456f32b1da7b389621254ccd9102e6a49136c53854b ql/lib/codeql/swift/elements/decl/ClassDeclConstructor.qll 0092ab4b76cd858489d76be94a43442c0e5f395b1d5684309674957e107979b7 9bc496e483feb88552ca0d48e32039aa4566f4612fc27073fea48ad954985d46 -ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll 43f54876f39f58beb1d0b8293976648d1e4f5585046a502835eb7befb278f6b0 3a07a73dc11ef06ddaeb3d401748ef14a1ee66447c86d2e8c8f187dda92b34a2 -ql/lib/codeql/swift/elements/decl/ConcreteFuncDeclConstructor.qll 4eb2e9dc8b4c93e457bb594085d8f50862dc07a712ce7a0f2dee7f108467ce3e 1f994d6ae1ca2e4fd5da075b70ea22322181bdaf43034face1e82ef353fe34bf ql/lib/codeql/swift/elements/decl/ConcreteVarDecl.qll 94bcbdd91f461295c5b6b49fa597b7e3384556c2383ad0c2a7c58276bade79e6 d821efa43c6d83aedfb959500de42c5ecabbf856f8556f739bc6cec30a88dfab ql/lib/codeql/swift/elements/decl/ConcreteVarDeclConstructor.qll 4b6a9f458db5437f9351b14464b3809a78194029554ea818b3e18272c17afba3 a60d695b0d0ffa917ad01908bec2beaa663e644eddb00fb370fbc906623775d4 -ql/lib/codeql/swift/elements/decl/ConstructorDeclConstructor.qll ba5cc6f440cba3d47b364a37febd64f85941cdc0237db52a2b8844d1dc75d483 9fc039ca7a0f33f03b3f573186f02efecbac0c2e0dc5abba5d47876ca26390fe -ql/lib/codeql/swift/elements/decl/DestructorDeclConstructor.qll c33b113a3ccb0b1bfd9aad8b909940776da5fdb8a24e1b998c5ebde3903be981 155ad928fbebf9688eec30a2cf61d9a2d4cd15d1161dc3f6202e6331bdb3a56a +ql/lib/codeql/swift/elements/decl/DeinitializerConstructor.qll 85f29a68ee5c0f2606c51e7a859f5f45fbc5f373e11b5e9c0762c9ba5cff51c4 6b28f69b8125d0393607dbad8e7a8aaa6469b9c671f67e8e825cc63964ed2f5d ql/lib/codeql/swift/elements/decl/EnumCaseDeclConstructor.qll 8c907544170671f713a8665d294eeefdbe78a607c2f16e2c630ea9c33f484baf eec83efc930683628185dbdad8f73311aad510074d168a53d85ea09d13f1f7e1 ql/lib/codeql/swift/elements/decl/EnumDecl.qll 29f9d8cbfb19c174af9a666162fd918af7f962fa5d97756105e78d5eec38cb9e 779940ebdbd510eb651972c57eb84b04af39c44ef59a8c307a44549ab730febb ql/lib/codeql/swift/elements/decl/EnumDeclConstructor.qll 642bbfb71e917d84695622f3b2c7b36bf5be4e185358609810267ab1fc4e221b f6e06d79e7ff65fbabf72c553508b67406fb59c577215d28cc47971d34b6af05 ql/lib/codeql/swift/elements/decl/EnumElementDeclConstructor.qll 736074246a795c14a30a8ec7bb8da595a729983187887294e485487309919dc6 4614fb380fad7af1b5fb8afce920f3e7350378254ece60d19722046046672fbb ql/lib/codeql/swift/elements/decl/ExtensionDeclConstructor.qll 4f811e3332720327d2b9019edbb2fa70fb24322e72881afc040e7927452409d6 554f9832311dfc30762507e0bd4b25c5b6fdb9d0c4e8252cc5a1ef1033fafacb -ql/lib/codeql/swift/elements/decl/FuncDecl.qll d3ff8bfb16c54b4d82bc2a0b9fe400bb511376d008eb0180859e7b6ad5c32b4a ba8e48682e93af0804e66f5bf0207049e291a0c1430a872252dc67af17ea700a ql/lib/codeql/swift/elements/decl/GenericContext.qll de30cdd5cdf05024dfd25dbe3be91607bd871b03a0d97c9d7c21430d7d5bb325 4747af5faf0a93d7508e0ec58021a842ca5ec41831b5d71cbc7fce2a2389a820 ql/lib/codeql/swift/elements/decl/GenericTypeDecl.qll ace55c6a6cea01df01a9270c38b0d9867dee1b733bca1d1b23070fc2fe1307a5 42e1e3e055f3e5fa70c8624910d635ab10fe4015d378be9e1e6e1adb39f0dc40 ql/lib/codeql/swift/elements/decl/GenericTypeParamDecl.qll 8d8c148342b4d77ecb9a849b7172708139509aca19f744b0badf422c07b6d47a 569a380917adf4e26b286343c654954d472eabf3fe91e0d1b5f26549d9c6d24e @@ -39,9 +36,12 @@ ql/lib/codeql/swift/elements/decl/IfConfigDeclConstructor.qll ebd945f0a081421bd7 ql/lib/codeql/swift/elements/decl/ImportDeclConstructor.qll f2f09df91784d7a6d348d67eaf3429780ac820d2d3a08f66e1922ea1d4c8c60d 4496865a26be2857a335cbc00b112beb78a319ff891d0c5d2ad41a4d299f0457 ql/lib/codeql/swift/elements/decl/InfixOperatorDecl.qll 58ba4d318b958d73e2446c6c8a839deb041ac965c22fbc218e5107c0f00763f8 5dec87f0c43948f38e942b204583043eb4f7386caa80cec8bf2857a2fd933ed4 ql/lib/codeql/swift/elements/decl/InfixOperatorDeclConstructor.qll ca6c5c477e35e2d6c45f8e7a08577c43e151d3e16085f1eae5c0a69081714b04 73543543dff1f9847f3299091979fdf3d105a84e2bcdb890ce5d72ea18bba6c8 +ql/lib/codeql/swift/elements/decl/InitializerConstructor.qll 6211d28a26085decb264a9f938523e6bb0be28b292705587042ca711f9c24ef8 23ac17f8c41e2864c9f6ae8ebd070332b4b8cd3845c6b70b55becab13994c446 ql/lib/codeql/swift/elements/decl/MissingMemberDeclConstructor.qll 82738836fa49447262e184d781df955429c5e3697d39bf3689397d828f04ce65 8ef82ed7c4f641dc8b4d71cd83944582da539c34fb3d946c2377883abada8578 ql/lib/codeql/swift/elements/decl/ModuleDecl.qll a6d2f27dc70a76ec8f3360322cde3961871222c8621d99fec3a3ac5762967687 410311bf3ae1efac53d8fd6515c2fe69d9ab79902c1048780e87d478cd200e26 ql/lib/codeql/swift/elements/decl/ModuleDeclConstructor.qll 9b18b6d3517fd0c524ac051fd5dea288e8f923ada00fe4cc809cbebce036f890 0efc90492417089b0982a9a6d60310faba7a1fce5c1749396e3a29b3aac75dc5 +ql/lib/codeql/swift/elements/decl/NamedFunction.qll cc1c257510d5698c219aa3b6715f9d638eb2f3d9bd77d83754b0a7982aa06902 c697db806e9f0fdfaf5699107f322bd1b5d379f80d046e6bef18b10be3be73c2 +ql/lib/codeql/swift/elements/decl/NamedFunctionConstructor.qll 4a2e34be5e3b18f67c9a84d07d3ba8b5e5130c752548ea50ac5307168efea249 0f1e1e49abd10fb9f4391ad0676bd34ab5c2c24a6e7be6b3293a4459783b28a1 ql/lib/codeql/swift/elements/decl/OpaqueTypeDecl.qll 06e94ab2b5cebfc72a390dc420bb4c122d66e80de6d90a6bf77b230aab355f6e e84e0dd1a3175ad29123def00e71efbd6f4526a12601fc027b0892930602046b ql/lib/codeql/swift/elements/decl/OpaqueTypeDeclConstructor.qll f707aab3627801e94c63aedcded21eab14d3617c35da5cf317692eeb39c84710 20888ae6e386ae31e3cb9ff78155cb408e781ef1e7b6d687c2705843bcac0340 ql/lib/codeql/swift/elements/decl/ParamDeclConstructor.qll cfa0ba73a9727b8222efbf65845d6df0d01800646feaf7b407b8ffe21a6691d8 916ff2d3e96546eac6828e1b151d4b045ce5f7bcd5d7dbb074f82ecf126b0e09 @@ -62,7 +62,6 @@ ql/lib/codeql/swift/elements/decl/TypeAliasDecl.qll 984c5802c35e595388f7652cef1a ql/lib/codeql/swift/elements/decl/TypeAliasDeclConstructor.qll ba70bb69b3a14283def254cc1859c29963838f624b3f1062a200a8df38f1edd5 96ac51d1b3156d4139e583f7f803e9eb95fe25cc61c12986e1b2972a781f9c8b ql/lib/codeql/swift/elements/expr/AbiSafeConversionExpr.qll 39b856c89b8aff769b75051fd9e319f2d064c602733eaa6fed90d8f626516306 a87738539276438cef63145461adf25309d1938cfac367f53f53d33db9b12844 ql/lib/codeql/swift/elements/expr/AbiSafeConversionExprConstructor.qll 7d70e7c47a9919efcb1ebcbf70e69cab1be30dd006297b75f6d72b25ae75502a e7a741c42401963f0c1da414b3ae779adeba091e9b8f56c9abf2a686e3a04d52 -ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll 4027b51a171387332f96cb7b78ca87a6906aec76419938157ac24a60cff16519 400790fe643585ad39f40c433eff8934bbe542d140b81341bca3b6dfc5b22861 ql/lib/codeql/swift/elements/expr/AnyHashableErasureExpr.qll d6193ef0ba97877dfbdb3ea1c18e27dad5b5d0596b4b5b12416b31cbe1b3d1d6 bf80cab3e9ff5366a6223153409f4852acdb9e4a5d464fb73b2a8cffc664ca29 ql/lib/codeql/swift/elements/expr/AnyHashableErasureExprConstructor.qll 12816f18d079477176519a20b0f1262fc84da98f60bce3d3dd6476098c6542e7 4cc5c8492a97f4639e7d857f2fca9065293dfa953d6af451206ce911cda9f323 ql/lib/codeql/swift/elements/expr/AnyTryExpr.qll 4a56bb49ed1d9f3c81c1c6cce3c60657e389facd87807eaefa407532259cec70 988b5df28972e877486704a43698ada91e68fe875efc331f0d7139c78b36f7dd @@ -90,7 +89,6 @@ ql/lib/codeql/swift/elements/expr/CaptureListExprConstructor.qll 03af12d1b10bdc2 ql/lib/codeql/swift/elements/expr/CheckedCastExpr.qll 440eeee832401584f46779389d93c2a4faa93f06bd5ea00a6f2049040ae53847 e7c90a92829472335199fd7a8e4ba7b781fbbf7d18cf12d6c421ddb22c719a4b ql/lib/codeql/swift/elements/expr/ClassMetatypeToObjectExpr.qll 9830ef94d196c93e016237c330a21a9d935d49c3d0493e597c3e29804940b29e 4b5aca9fa4524dc25dc6d12eb32eeda179a7e7ec20f4504493cf7eb828a8e7be ql/lib/codeql/swift/elements/expr/ClassMetatypeToObjectExprConstructor.qll 369cecb4859164413d997ee4afba444853b77fb857fa2d82589603d88d01e1dc 3b4ebd1fb2e426cba21edd91b36e14dc3963a1ede8c482cdf04ef5003a290b28 -ql/lib/codeql/swift/elements/expr/ClosureExprConstructor.qll cf2fa2dab328f6b98aeffcdc833de4d74f69d23779ac897f5ada9c2dca9ef093 13f85b735ebb56c361458baba45eb854e70b7987d5e1863e564084c1a6165cc5 ql/lib/codeql/swift/elements/expr/CoerceExpr.qll e68c125466a36af148f0e47ff1d22b13e9806a40f1ec5ddc540d020d2ab7c7dc eb13ef05c7436d039c1f8a4164b039bdbf12323310c249d7702291058f244d38 ql/lib/codeql/swift/elements/expr/CoerceExprConstructor.qll aa80ea0e6c904fab461c463137ce1e755089c3990f789fae6a0b29dea7013f6d 455f5184a3d2e2a6b9720a191f1f568699f598984779d923c2b28e8a3718fa9d ql/lib/codeql/swift/elements/expr/CollectionExpr.qll ec0e46338e028821afe1bafb2bed4edc9c9a9f69b65b397c3c0914eb52851bb0 87977b7661bcd8212b07b36f45ff94f5e98513c6dddb4cca697d1d6b853dff72 @@ -100,7 +98,6 @@ ql/lib/codeql/swift/elements/expr/ConditionalBridgeFromObjCExpr.qll 4ff4d0e9f4af ql/lib/codeql/swift/elements/expr/ConditionalBridgeFromObjCExprConstructor.qll 7350d9e279995181f08dcc931723d21a36aac17b3ea5b633c82bac5c7aeb733a dc6767f621bddcc22be8594b46b7d3170e5d7bfcee6f1e0279c26492fd88c81d ql/lib/codeql/swift/elements/expr/ConditionalCheckedCastExpr.qll 3052583ee44e9c859dddefc2ee578710c7ac272ba82eb939e2299008da0c92db a66a1e07b210a1e8d999380db04a8b3210b66049a876bd92c8f56eae66c5a062 ql/lib/codeql/swift/elements/expr/ConditionalCheckedCastExprConstructor.qll 13a1032bfa1199245746d4aac2c54d3ba336d3580c2713a66a91ad47eb8648ca 2a7c66669551aaa3528d77a8525985b850acbc983fea6f076561709a076dadb7 -ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll 2d8709f776df9edda8f1c07884fc32d1d25306cc2e8029d7b0c74d91f3828fef fc4b855b27f7afefab8132bd2adc3567cceec6b2fd762bf1dc7463ce76421326 ql/lib/codeql/swift/elements/expr/CovariantFunctionConversionExpr.qll 0d18efcc60908890fa4ebf3ef90b19b06a4140d06ec90053ab33db3ad864281a 4510d77d211f4b6db9dd4c941706d7eb7579fe7311714758c9d1d24513bfbdc4 ql/lib/codeql/swift/elements/expr/CovariantFunctionConversionExprConstructor.qll eac12524819e9fe29074f90ea89fea866023b5ed4a5494345f2b9d8eec531620 71a6eb320630f42403e1e67bb37c39a1bae1c9f6cc38c0f1688a31f3f206d83f ql/lib/codeql/swift/elements/expr/CovariantReturnConversionExpr.qll baa7e9a3c2a2de383d55fac1741b8739c389b9c3cf7a0241d357d226364daaf3 720fb172ebcb800c70810539c7a80dbdf61acb970277f2b6a54b9159ab4e016e @@ -130,6 +127,8 @@ ql/lib/codeql/swift/elements/expr/ErrorExpr.qll 8a68131297e574625a22fbbb28f3f090 ql/lib/codeql/swift/elements/expr/ErrorExprConstructor.qll dd2bec0e35121e0a65d47600100834963a7695c268e3832aad513e70b1b92a75 e85dcf686403511c5f72b25ae9cf62f77703575137c39610e61562efc988bbac ql/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExpr.qll 420d534f76e192e89f29c71a7282e0697d259c00a7edc3e168ca895b0dc4f1d1 c0b5811c8665f3324b04d40f5952a62e631ec4b3f00db8e9cc13cb5d60028178 ql/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExprConstructor.qll 1a735425a59f8a2bd208a845e3b4fc961632c82db3b69d0b71a1bc2875090f3b 769b6a80a451c64cbf9ce09729b34493a59330d4ef54ab0d51d8ff81305b680f +ql/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll 77626fd66735b1954e6ec80a50a36ce94dd725110a5051ab4034600c8ce5ca6f 4e169380503b98d00efd9f38e549621c21971ed9e92dbce601fb46df2f44de78 +ql/lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll 171d9f028bfb80754ddc917d0f6a24185d30643c6c2c80a8a5681dba16a4c48e 0e560df706726c7d45ea95532a9e4df00c03e860b840179f973bab8009c437ab ql/lib/codeql/swift/elements/expr/FloatLiteralExprConstructor.qll 4dfb34d32e4022b55caadcfbe147e94ebe771395c59f137228213a51a744ba10 1eb78fcda9e0b70d1993e02408fb6032035991bf937c4267149ab9c7c6a99d3a ql/lib/codeql/swift/elements/expr/ForceTryExprConstructor.qll 48cbc408bb34a50558d25aa092188e1ad0f68d83e98836e05072037f3d8b49af 62ce7b92410bf712ecd49d3eb7dd9b195b9157415713aaf59712542339f37e4c ql/lib/codeql/swift/elements/expr/ForceValueExprConstructor.qll 3b201ee2d70ab13ad7e3c52aad6f210385466ec4a60d03867808b4d3d97511a8 d5d9f0e7e7b4cae52f97e4681960fa36a0c59b47164868a4a099754f133e25af @@ -143,6 +142,7 @@ ql/lib/codeql/swift/elements/expr/IfExprConstructor.qll 19450ccaa41321db4114c275 ql/lib/codeql/swift/elements/expr/InOutExprConstructor.qll c8c230f9a396acadca6df83aed6751ec1710a51575f85546c2664e5244b6c395 2e354aca8430185889e091ddaecd7d7df54da10706fe7fe11b4fa0ee04d892e0 ql/lib/codeql/swift/elements/expr/InOutToPointerExpr.qll 145616d30d299245701f15417d02e6e90a6aa61b33326bfd4bc2a2d69bed5551 e9c7db3671cce65c775760c52d1e58e91903ad7be656457f096bfe2abab63d29 ql/lib/codeql/swift/elements/expr/InOutToPointerExprConstructor.qll 06b1377d3d7399ef308ba3c7787192446452a4c2e80e4bb9e235267b765ae05d 969680fddeb48d9e97c05061ae9cbc56263e4c5ad7f4fad5ff34fdaa6c0010b4 +ql/lib/codeql/swift/elements/expr/InitializerRefCallExpr.qll 9df0739f61bab51895c51acdc9d5889693c4466a522fcd05d402ad7c9436682e 1695a0e6f88bd59de32d75d4cb2bd41ffc97a42818ef2ed10fe785aa87bfb28f ql/lib/codeql/swift/elements/expr/InjectIntoOptionalExpr.qll 79d859152f5fde76e28b8b01e3ba70ec481650b39e2a686fc6898759948bc716 6ec93a725c92a9abf62c39451eaf6435942b61b56bd06db0d494da0b5f407441 ql/lib/codeql/swift/elements/expr/InjectIntoOptionalExprConstructor.qll e25cee8b12b0640bfcc652973bbe677c93b4cb252feba46f9ffe3d822f9d97e0 4211336657fce1789dcdc97d9fe75e6bc5ab3e79ec9999733488e0be0ae52ca2 ql/lib/codeql/swift/elements/expr/IntegerLiteralExprConstructor.qll 779c97ef157265fa4e02dacc6ece40834d78e061a273d30773ac2a444cf099d0 d57c9e8bbb04d8c852906a099dc319473ae126b55145735b0c2dc2b671e1bcbd @@ -151,7 +151,7 @@ ql/lib/codeql/swift/elements/expr/IsExprConstructor.qll 0dc758a178c448c453fb3902 ql/lib/codeql/swift/elements/expr/KeyPathApplicationExprConstructor.qll c58c6812821d81dfb724fd37f17b2d80512c0584cf79e58ebb3a9657199e8f91 a4b9d8369f0224f9878bf20fcad4047756e26592fb7848988bdb96e463236440 ql/lib/codeql/swift/elements/expr/KeyPathDotExprConstructor.qll d112a3a1c1b421fc6901933685179232ac37134270482a5b18d96ba6f78a1fd1 abce0b957bdf2c4b7316f4041491d31735b6c893a38fbf8d96e700a377617b51 ql/lib/codeql/swift/elements/expr/KeyPathExprConstructor.qll 96f7bc80a1364b95f5a02526b3da4f937abe6d8672e2a324d57c1b036389e102 2f65b63e8eac280b338db29875f620751c8eb14fbdcf6864d852f332c9951dd7 -ql/lib/codeql/swift/elements/expr/LazyInitializerExprConstructor.qll deba52e51f31504564adc33da079b70f1f2da1e3e6f9538cba8bf97be0c27c64 4499c688d86c08cb33a754ad86f6adbe47754aa0fc58a4d77dd7cbfa1ca1fa50 +ql/lib/codeql/swift/elements/expr/LazyInitializationExprConstructor.qll 4f81a962f7406230323f422546bba2176ac20aef75a67cab62e11612946b2176 5ed2b68fd3667688dca83f1db89ebdb01c0f6f67b50b824a03940aeb41b834a3 ql/lib/codeql/swift/elements/expr/LinearFunctionExpr.qll 37fc05646e4fbce7332fb544e3c1d053a2f2b42acb8ce1f3a9bb19425f74ae34 b3253571f09a743a235c0d27384e72cf66b26ba8aa5e34061956c63be4940f15 ql/lib/codeql/swift/elements/expr/LinearFunctionExprConstructor.qll 18998356c31c95a9a706a62dd2db24b3751015878c354dc36aa4655e386f53c3 7e02b4801e624c50d880c2826ef7149ad609aa896d194d64f715c16cfbd11a7d ql/lib/codeql/swift/elements/expr/LinearFunctionExtractOriginalExpr.qll c968bca2c79985d8899e37a4015de2a6df6fd40f6e519f8f0601202c32c68f70 bd9f3c1a5114cec5c360a1bb94fe2ffaa8559dfdd69d78bd1a1c039b9d0cab10 @@ -179,7 +179,7 @@ ql/lib/codeql/swift/elements/expr/OpenExistentialExprConstructor.qll c56e5e6f7ae ql/lib/codeql/swift/elements/expr/OptionalEvaluationExpr.qll bba59c32fbe7e76ddf07b8bbe68ce09587f490687e6754c2210e13bda055ba25 559902efedbf4c5ef24697267c7b48162129b4ab463b41d89bdfb8b94742fa9f ql/lib/codeql/swift/elements/expr/OptionalEvaluationExprConstructor.qll 4ba0af8f8b4b7920bc1106d069455eb754b7404d9a4bfc361d2ea22e8763f4fe 6d07e7838339290d1a2aec88addd511f01224d7e1d485b08ef4793e01f4b4421 ql/lib/codeql/swift/elements/expr/OptionalTryExprConstructor.qll 60d2f88e2c6fc843353cc52ce1e1c9f7b80978750d0e780361f817b1b2fea895 4eabd9f03dc5c1f956e50e2a7af0535292484acc69692d7c7f771e213609fd04 -ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll cf726ed7ed830e17aaedf1acddf1edc4efc7d72ab9f9580bc89cc8eefbd54d8a 4ef3010dc5500bd503db8aa531d5455a9c80bc30172fb005abc6459b6f66ea00 +ql/lib/codeql/swift/elements/expr/OtherInitializerRefExprConstructor.qll 6d0fdbcf2d8e321e576947345c1bdb49b96b3cc7689598e28c77aa79baf55d62 a7aa3163f0437975db0d0a8e3fe4224c05f0ad0a03348f7c6ec3edc37f90530c ql/lib/codeql/swift/elements/expr/OverloadedDeclRefExpr.qll 97e35eda07e243144652648342621a67745c0b3b324940777d38a4a293968cf6 47b1c6df5397de490f62e96edc0656b1f97c0be73c6b99ecd78b62d46106ce61 ql/lib/codeql/swift/elements/expr/OverloadedDeclRefExprConstructor.qll 2cf79b483f942fbf8aaf9956429b92bf9536e212bb7f7940c2bc1d30e8e8dfd5 f4c16a90e3ab944dded491887779f960e3077f0a8823f17f50f82cf5b9803737 ql/lib/codeql/swift/elements/expr/ParenExprConstructor.qll 6baaa592db57870f5ecd9be632bd3f653c44d72581efd41e8a837916e1590f9e 6f28988d04b2cb69ddcb63fba9ae3166b527803a61c250f97e48ff39a28379f6 @@ -191,7 +191,7 @@ ql/lib/codeql/swift/elements/expr/PropertyWrapperValuePlaceholderExpr.qll d4b6e3 ql/lib/codeql/swift/elements/expr/PropertyWrapperValuePlaceholderExprConstructor.qll 874da84b8ac2fbf6f44e5343e09629225f9196f0f1f3584e6bc314e5d01d8593 e01fc8f9a1d1cddab7c249437c13f63e8dc93e7892409791728f82f1111ac924 ql/lib/codeql/swift/elements/expr/ProtocolMetatypeToObjectExpr.qll b43455289de611ba68870298e89ad6f94b5edbac69d3a22b3a91046e95020913 1f342dead634daf2cd77dd32a1e59546e8c2c073e997108e17eb2c3c832b3070 ql/lib/codeql/swift/elements/expr/ProtocolMetatypeToObjectExprConstructor.qll aaaf5fd2496e24b341345933a5c730bbfd4de31c5737e22269c3f6927f8ae733 bece45f59dc21e9deffc1632aae52c17cf41924f953afc31a1aa94149ecc1512 -ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll 434e00b6e5d3ccf356dabb4a7d6574966676c32d4c257ad3606d5b9e2b715524 637a16d0f5f504bad4a04bb85d6491a94738781d3282bc27363cceafb3023408 +ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExprConstructor.qll 7d0d0c89dc155276334778166bfdad5f664ffb886eab568c49eef04ad3e773f3 8f60626aec107516224c10ef3e03d683ce9d7eb7faa7607289c25afc4625ee15 ql/lib/codeql/swift/elements/expr/RegexLiteralExprConstructor.qll 7bf1bdba26d38e8397a9a489d05042ea2057f06e35f2a664876dc0225e45892d dcc697170a9fc03b708f4a13391395e3986d60eb482639e3f5a3ba0984b72349 ql/lib/codeql/swift/elements/expr/SelfApplyExpr.qll 986b3ff9833aac59facecea185517c006264c5011191b4c7f31317a20926467a f0349628f9ead822783e09e56e0721f939bfb7f59c8661e6155b5a7d113c26f3 ql/lib/codeql/swift/elements/expr/SequenceExpr.qll 813360eff6a312e39c7b6c49928477679a3f32314badf3383bf6204690a280e4 3b2d06ac54746033a90319463243f2d0f17265c7f1573cbfedbdca3fb7063fd2 @@ -366,7 +366,7 @@ ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 325e4c4481e9ac07acdc6 ql/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856 ql/lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996 ql/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897 -ql/lib/codeql/swift/elements.qll d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b +ql/lib/codeql/swift/elements.qll 3df0060edd2b2030f4e4d7d5518afe0073d798474d9b1d6185d833bec63ca8bd 3df0060edd2b2030f4e4d7d5518afe0073d798474d9b1d6185d833bec63ca8bd ql/lib/codeql/swift/generated/AstNode.qll 02ca56d82801f942ae6265c6079d92ccafdf6b532f6bcebd98a04029ddf696e4 6216fda240e45bd4302fa0cf0f08f5f945418b144659264cdda84622b0420aa2 ql/lib/codeql/swift/generated/AvailabilityInfo.qll 996a5cfadf7ca049122a1d1a1a9eb680d6a625ce28ede5504b172eabe7640fd2 4fe6e0325ff021a576fcd004730115ffaa60a2d9020420c7d4a1baa498067b60 ql/lib/codeql/swift/generated/AvailabilitySpec.qll fb1255f91bb5e41ad4e9c675a2efbc50d0fb366ea2de68ab7eebd177b0795309 144e0c2e7d6c62ecee43325f7f26dcf437881edf0b75cc1bc898c6c4b61fdeaf @@ -382,40 +382,40 @@ ql/lib/codeql/swift/generated/KeyPathComponent.qll f8d62b8021936dc152538b52278a3 ql/lib/codeql/swift/generated/Locatable.qll bdc98b9fb7788f44a4bf7e487ee5bd329473409950a8e9f116d61995615ad849 0b36b4fe45e2aa195e4bb70c50ea95f32f141b8e01e5f23466c6427dd9ab88fb ql/lib/codeql/swift/generated/Location.qll 851766e474cdfdfa67da42e0031fc42dd60196ff5edd39d82f08d3e32deb84c1 b29b2c37672f5acff15f1d3c5727d902f193e51122327b31bd27ec5f877bca3b ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 -ql/lib/codeql/swift/generated/ParentChild.qll 3998d73048297cf2df42176b0060c025e57d409d56f3fbfab9c202bd46c07b5e 425b01328baf38bd5e46403e11b25b0e17cd5bc40731dbf64a46e01604611e15 +ql/lib/codeql/swift/generated/ParentChild.qll 7db14da89a0dc22ab41e654750f59d03085de8726ac358c458fccb0e0b75e193 e16991b33eb0ddea18c0699d7ea31710460ff8ada1f51d8e94f1100f6e18d1c8 ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -ql/lib/codeql/swift/generated/Raw.qll cda40b44e2b72ceb32a3c03d2f16028fc4db723c8cdc0a9638693794f4f07411 eb4b59f4dbd2159f59132994e6d1840a1273e5c316232b8439ddc0cc08ef8736 -ql/lib/codeql/swift/generated/Synth.qll e26debaea7feaabbdd4180983a03fa406584e2a0dc4902520d5549d106770fee a448e51acba628d63fc4ae59aa23efa7cd5b567230ae24749d31d2a4ad51baf9 -ql/lib/codeql/swift/generated/SynthConstructors.qll bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8 bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8 +ql/lib/codeql/swift/generated/Raw.qll 8d4880e5ee1fdd120adeb7bf0dfa1399e7b1a53b2cc7598aed8e15cbf996d1c0 da0d446347d29f5cd05281c17c24e87610f31c32adb7e05ab8f3a26bed55bd90 +ql/lib/codeql/swift/generated/Synth.qll 551fdf7e4b53f9ee1314d1bb42c2638cf82f45bfa1f40a635dfa7b6072e4418c 9ab178464700a19951fc5285acacda4913addee81515d8e072b3d7055935a814 +ql/lib/codeql/swift/generated/SynthConstructors.qll 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 ql/lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 ql/lib/codeql/swift/generated/UnknownLocation.qll e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 ql/lib/codeql/swift/generated/UnspecifiedElement.qll dbc6ca4018012977b26ca184a88044c55b0661e3998cd14d46295b62a8d69625 184c9a0ce18c2ac881943b0fb400613d1401ed1d5564f90716b6c310ba5afe71 -ql/lib/codeql/swift/generated/decl/AbstractFunctionDecl.qll 76408e1672fe4c18d00e6027171a88a994639034bd90052effb649d472b15478 c819f02330635fd3138ae1ebaae49a397c3271d78fbce6e2ecc015bb122de3f9 -ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll 882e95e6887741c0cdac4dcafb9efb5182f18484c6d29e84bab0a8f65c9e70a2 0c5c6739484ce3913cfbff68307a5c1cf63639e5ba9043f1f305197fc06b8de9 +ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll faac7645fae432c8aa5d970a0e5bdc12946124d3a206deb133d623cbbf06e64e 221c8dbac988bfce1b4c3970dfb97b91b30dff8ac196e1fbde5eb5189cfcadf0 ql/lib/codeql/swift/generated/decl/AbstractTypeParamDecl.qll 1e268b00d0f2dbbd85aa70ac206c5e4a4612f06ba0091e5253483635f486ccf9 5479e13e99f68f1f347283535f8098964f7fd4a34326ff36ad5711b2de1ab0d0 -ql/lib/codeql/swift/generated/decl/AccessorDecl.qll 443cb9888dbdbaee680bf24469ce097a8292806dc53f0b109d492db621fa00aa 0dbe38cbbd3f3cd880c1569d9d42165e7cf0358da0cc7cb63e89890310ad40a0 +ql/lib/codeql/swift/generated/decl/Accessor.qll c93cdf7dbb87e6c9b09b5fcf469b952041f753914a892addeb24bb46eaa51d29 1e8104da2da146d3e4d8f5f96b87872e63162e53b46f9c7038c75db51a676599 +ql/lib/codeql/swift/generated/decl/AccessorOrNamedFunction.qll b78aaef06cdaa172dce3e1dcd6394566b10ce445906e3cf67f6bef951b1662a4 a30d9c2ff79a313c7d0209d72080fdc0fabf10379f8caed5ff2d72dc518f8ad3 ql/lib/codeql/swift/generated/decl/AssociatedTypeDecl.qll 4169d083104f9c089223ed3c5968f757b8cd6c726887bbb6fbaf21f5ed7ee144 4169d083104f9c089223ed3c5968f757b8cd6c726887bbb6fbaf21f5ed7ee144 ql/lib/codeql/swift/generated/decl/CapturedDecl.qll 18ce5a5d548abb86787096e26ffd4d2432eda3076356d50707a3490e9d3d8459 42708248ba4bcd00a628e836ea192a4b438c0ffe91e31d4e98e497ef896fabac ql/lib/codeql/swift/generated/decl/ClassDecl.qll a60e8af2fdbcd20cfa2049660c8bcbbc00508fbd3dde72b4778317dfc23c5ae4 a60e8af2fdbcd20cfa2049660c8bcbbc00508fbd3dde72b4778317dfc23c5ae4 -ql/lib/codeql/swift/generated/decl/ConcreteFuncDecl.qll c7192e79ce67f77df36575cceb942f11b182c26c93899469654316de2d543cf9 c7192e79ce67f77df36575cceb942f11b182c26c93899469654316de2d543cf9 ql/lib/codeql/swift/generated/decl/ConcreteVarDecl.qll 4801ccc477480c4bc4fc117976fbab152e081064e064c97fbb0f37199cb1d0a8 4d7cfbf5b39b307dd673781adc220fdef04213f2e3d080004fa658ba6d3acb8d -ql/lib/codeql/swift/generated/decl/ConstructorDecl.qll 20e3a37809eacfc43828fa61248ad19b0ff610faad3a12b82b3cf5ed2bcce13c 20e3a37809eacfc43828fa61248ad19b0ff610faad3a12b82b3cf5ed2bcce13c ql/lib/codeql/swift/generated/decl/Decl.qll 18f93933c2c00955f6d28b32c68e5b7ac13647ebff071911b26e68dbc57765a7 605e700ab8d83645f02b63234fee9d394b96caba9cad4dd80b3085c2ab63c33d -ql/lib/codeql/swift/generated/decl/DestructorDecl.qll 8767e3ddabdf05ea5ee99867e9b77e67f7926c305b2fba1ca3abf94e31d836b9 8767e3ddabdf05ea5ee99867e9b77e67f7926c305b2fba1ca3abf94e31d836b9 +ql/lib/codeql/swift/generated/decl/Deinitializer.qll 816ecd92552915d06952517606a6e4c67bc53d7e7d9f5c09b7276e70612627fe 816ecd92552915d06952517606a6e4c67bc53d7e7d9f5c09b7276e70612627fe ql/lib/codeql/swift/generated/decl/EnumCaseDecl.qll f71c9d96db8260462c34e5d2bd86dda9b977aeeda087c235b873128b63633b9c e12ff7c0173e3cf9e2b64de66d8a7f2246bc0b2cb721d25b813d7a922212b35a ql/lib/codeql/swift/generated/decl/EnumDecl.qll fa4490d511ee537751a4fab2478e65250ff3deba43c74db5341184c9ba25b534 fa4490d511ee537751a4fab2478e65250ff3deba43c74db5341184c9ba25b534 ql/lib/codeql/swift/generated/decl/EnumElementDecl.qll 5ef4f6839f4f19f29fabd04b653e89484fa68a7e7ec94101a5201aa13d89e9eb 78006fa52b79248302db04348bc40f2f77edf101b6e429613f3089f70750fc11 ql/lib/codeql/swift/generated/decl/ExtensionDecl.qll 8129015990b6c80cedb796ae0768be2b9c040b5212b5543bc4d6fd994cc105f3 038b06a0c0eeb1ad7e31c995f20aaf4f8804001654ebb0e1e292d7e739a6c8ee -ql/lib/codeql/swift/generated/decl/FuncDecl.qll 11ebe386dd06937c84fdb283a73be806763d939c163d3c0fd0c4c3eb1caeda41 6a5b6854818cb3d2bc76f0abdee4933ca839c182abd07fb4d271400f5267f6e2 +ql/lib/codeql/swift/generated/decl/Function.qll 92d1fbceb9e96afd00a1dfbfd15cec0063b3cba32be1c593702887acc00a388a 0cbae132d593b0313a2d75a4e428c7f1f07a88c1f0491a4b6fa237bb0da71df3 ql/lib/codeql/swift/generated/decl/GenericContext.qll 4c7bd7fd372c0c981b706de3a57988b92c65c8a0d83ea419066452244e6880de 332f8a65a6ae1cad4aa913f2d0a763d07393d68d81b61fb8ff9912b987c181bb ql/lib/codeql/swift/generated/decl/GenericTypeDecl.qll 71f5c9c6078567dda0a3ac17e2d2d590454776b2459267e31fed975724f84aec 669c5dbd8fad8daf007598e719ac0b2dbcb4f9fad698bffb6f1d0bcd2cee9102 ql/lib/codeql/swift/generated/decl/GenericTypeParamDecl.qll bc41a9d854e65b1e0da86350870a8fe050eb1dc031cd17ded11c15b5ad8ad183 bc41a9d854e65b1e0da86350870a8fe050eb1dc031cd17ded11c15b5ad8ad183 ql/lib/codeql/swift/generated/decl/IfConfigDecl.qll 58c1a02a3867105c61d29e2d9bc68165ba88a5571aac0f91f918104938178c1e f74ef097848dd5a89a3427e3d008e2299bde11f1c0143837a8182572ac26f6c9 ql/lib/codeql/swift/generated/decl/ImportDecl.qll 8892cd34d182c6747e266e213f0239fd3402004370a9be6e52b9747d91a7b61b 2c07217ab1b7ebc39dc2cb20d45a2b1b899150cabd3b1a15cd8b1479bab64578 ql/lib/codeql/swift/generated/decl/InfixOperatorDecl.qll d98168fdf180f28582bae8ec0242c1220559235230a9c94e9f479708c561ea21 aad805aa74d63116b19f435983d6df6df31cef6a5bbd30d7c2944280b470dee6 +ql/lib/codeql/swift/generated/decl/Initializer.qll a72005f0abebd31b7b91f496ddae8dff49a027ba01b5a827e9b8870ecf34de17 a72005f0abebd31b7b91f496ddae8dff49a027ba01b5a827e9b8870ecf34de17 ql/lib/codeql/swift/generated/decl/MissingMemberDecl.qll eaf8989eda461ec886a2e25c1e5e80fc4a409f079c8d28671e6e2127e3167479 d74b31b5dfa54ca5411cd5d41c58f1f76cfccc1e12b4f1fdeed398b4faae5355 ql/lib/codeql/swift/generated/decl/ModuleDecl.qll 0b809c371dae40cfdc7bf869c654158dc154e1551d8466c339742c7fdc26a5db 3d7efb0ccfd752d9f01624d21eba79067824b3910b11185c81f0b513b69e8c51 +ql/lib/codeql/swift/generated/decl/NamedFunction.qll e8c23d8344768fb7ffe31a6146952fb45f66e25c2dd32c91a6161aaa612e602f e8c23d8344768fb7ffe31a6146952fb45f66e25c2dd32c91a6161aaa612e602f ql/lib/codeql/swift/generated/decl/NominalTypeDecl.qll 7e8980cd646e9dee91e429f738d6682b18c8f8974c9561c7b936fca01b56fdb2 513e55dd6a68d83a8e884c9a373ecd70eca8e3957e0f5f6c2b06696e4f56df88 ql/lib/codeql/swift/generated/decl/OpaqueTypeDecl.qll f2cdbc238b9ea67d5bc2defd8ec0455efafd7fdaeca5b2f72d0bbb16a8006d17 041724a6ec61b60291d2a68d228d5f106c02e1ba6bf3c1d3d0a6dda25777a0e5 ql/lib/codeql/swift/generated/decl/OperatorDecl.qll 3ffdc7ab780ee94a975f0ce3ae4252b52762ca8dbea6f0eb95f951e404c36a5b 25e39ccd868fa2d1fbce0eb7cbf8e9c2aca67d6fd42f76e247fb0fa74a51b230 @@ -434,7 +434,6 @@ ql/lib/codeql/swift/generated/decl/TypeDecl.qll 74bb5f0fe2648d95c84fdce804740f2b ql/lib/codeql/swift/generated/decl/ValueDecl.qll 7b4e4c9334be676f242857c77099306d8a0a4357b253f8bc68f71328cedf1f58 f18938c47f670f2e0c27ffd7e31e55f291f88fb50d8e576fcea116d5f9e5c66d ql/lib/codeql/swift/generated/decl/VarDecl.qll bdea76fe6c8f721bae52bbc26a2fc1cbd665a19a6920b36097822839158d9d3b 9c91d8159fd7a53cba479d8c8f31f49ad2b1e2617b8cd9e7d1a2cb4796dfa2da ql/lib/codeql/swift/generated/expr/AbiSafeConversionExpr.qll f4c913df3f1c139a0533f9a3a2f2e07aee96ab723c957fc7153d68564e4fdd6d f4c913df3f1c139a0533f9a3a2f2e07aee96ab723c957fc7153d68564e4fdd6d -ql/lib/codeql/swift/generated/expr/AbstractClosureExpr.qll f0060c2972d2e1f9818d8deea3ceebbbe0b19d2ce11adc9b670beb672c4564d3 5f2500c5f3728f81599bd4e1fb9c97ac5a44a6dce8c1ab84a850c62aae3741ff ql/lib/codeql/swift/generated/expr/AnyHashableErasureExpr.qll f450ac8e316def1cd64dcb61411bae191144079df7f313a5973e59dc89fe367f f450ac8e316def1cd64dcb61411bae191144079df7f313a5973e59dc89fe367f ql/lib/codeql/swift/generated/expr/AnyTryExpr.qll f2929f39407e1717b91fc41f593bd52f1ae14c619d61598bd0668a478a04a91e 62693c2c18678af1ff9ce5393f0dd87c5381e567b340f1a8a9ecf91a92e2e666 ql/lib/codeql/swift/generated/expr/AppliedPropertyWrapperExpr.qll 191612ec26b3f0d5a61301789a34d9e349b4c9754618760d1c0614f71712e828 cc212df0068ec318c997a83dc6e95bdda5135bccc12d1076b0aebf245da78a4b @@ -444,7 +443,7 @@ ql/lib/codeql/swift/generated/expr/Argument.qll fe3cf5660e46df1447eac88c97da79b2 ql/lib/codeql/swift/generated/expr/ArrayExpr.qll 48f9dce31e99466ae3944558584737ea1acd9ce8bf5dc7f366a37de464f5570f ea13647597d7dbc62f93ddbeb4df33ee7b0bd1d9629ced1fc41091bbbe74db9c ql/lib/codeql/swift/generated/expr/ArrayToPointerExpr.qll afa9d62eb0f2044d8b2f5768c728558fe7d8f7be26de48261086752f57c70539 afa9d62eb0f2044d8b2f5768c728558fe7d8f7be26de48261086752f57c70539 ql/lib/codeql/swift/generated/expr/AssignExpr.qll b9cbe998daccc6b8646b754e903667de171fefe6845d73a952ae9b4e84f0ae13 14f1972f704f0b31e88cca317157e6e185692f871ba3e4548c9384bcf1387163 -ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll 26f2ef81e6e66541da75316f894498e74525c0703076cf67398c73a7cbd9736e 26f2ef81e6e66541da75316f894498e74525c0703076cf67398c73a7cbd9736e +ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll 5263d04d6d85ab7a61982cde5da1a3a6b92c0fa1fb1ddf5c651b90ad2fad59b9 5263d04d6d85ab7a61982cde5da1a3a6b92c0fa1fb1ddf5c651b90ad2fad59b9 ql/lib/codeql/swift/generated/expr/AwaitExpr.qll e17b87b23bd71308ba957b6fe320047b76c261e65d8f9377430e392f831ce2f1 e17b87b23bd71308ba957b6fe320047b76c261e65d8f9377430e392f831ce2f1 ql/lib/codeql/swift/generated/expr/BinaryExpr.qll 5ace1961cd6d6cf67960e1db97db177240acb6c6c4eba0a99e4a4e0cc2dae2e3 5ace1961cd6d6cf67960e1db97db177240acb6c6c4eba0a99e4a4e0cc2dae2e3 ql/lib/codeql/swift/generated/expr/BindOptionalExpr.qll 79b8ade1f9c10f4d5095011a651e04ea33b9280cacac6e964b50581f32278825 38197be5874ac9d1221e2d2868696aceedf4d10247021ca043feb21d0a741839 @@ -453,16 +452,15 @@ ql/lib/codeql/swift/generated/expr/BridgeFromObjCExpr.qll b9a6520d01613dfb8c7606 ql/lib/codeql/swift/generated/expr/BridgeToObjCExpr.qll 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d 31ca13762aee9a6a17746f40ec4e1e929811c81fdadb27c48e0e7ce6a3a6222d ql/lib/codeql/swift/generated/expr/BuiltinLiteralExpr.qll 052f8d0e9109a0d4496da1ae2b461417951614c88dbc9d80220908734b3f70c6 536fa290bb75deae0517d53528237eab74664958bf7fdbf8041283415dda2142 ql/lib/codeql/swift/generated/expr/CallExpr.qll c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 c7dc105fcb6c0956e20d40f736db35bd7f38f41c3d872858972c2ca120110d36 -ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll dc669082d0c123af7b3aa9f46c2eea3e339b2dd094cb8cab1aa0c8981567580f 3ffc0f61f7ca1333496d81df868cf1dcad004c70901b96144d5af64928027619 +ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll 1366d946d7faff63437c937e71392b505564c944947d25bb9628a86bec9919c2 e8c91265bdbe1b0902c3ffa84252b89ada376188c1bab2c9dde1900fd6bf992b ql/lib/codeql/swift/generated/expr/CheckedCastExpr.qll 146c24e72cda519676321d3bdb89d1953dfe1810d2710f04cfdc4210ace24c40 91093e0ba88ec3621b538d98454573b5eea6d43075a2ab0a08f80f9b9be336d3 ql/lib/codeql/swift/generated/expr/ClassMetatypeToObjectExpr.qll 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf 076c0f7369af3fffc8860429bd8e290962bf7fc8cf53bbba061de534e99cc8bf -ql/lib/codeql/swift/generated/expr/ClosureExpr.qll 4c20a922fc4c1f2a0f77026436282d056d0d188cc038443cca0d033dc57cf5a9 4c20a922fc4c1f2a0f77026436282d056d0d188cc038443cca0d033dc57cf5a9 +ql/lib/codeql/swift/generated/expr/ClosureExpr.qll f194fc8c5f67fcf0219e8e2de93ee2b820c27a609b2986b68d57a54445f66b61 3cae87f6c6eefb32195f06bc4c95ff6634446ecf346d3a3c94dc05c1539f3de2 ql/lib/codeql/swift/generated/expr/CoerceExpr.qll a2656e30dff4adc693589cab20e0419886959c821e542d7f996ab38613fa8456 a2656e30dff4adc693589cab20e0419886959c821e542d7f996ab38613fa8456 ql/lib/codeql/swift/generated/expr/CollectionExpr.qll 8782f55c91dc77310d9282303ba623cb852a4b5e7a8f6426e7df07a08efb8819 b2ce17bf217fe3df3da54ac2a9896ab052c1daaf5559a5c73cc866ca255a6b74 ql/lib/codeql/swift/generated/expr/CollectionUpcastConversionExpr.qll 2d007ed079803843a4413466988d659f78af8e6d06089ed9e22a0a8dedf78dbe ca7c3a62aa17613c5cbdc3f88ec466e7cc1d9adf5a73de917899b553c55c4c3f ql/lib/codeql/swift/generated/expr/ConditionalBridgeFromObjCExpr.qll 4a21e63cc547021b70ca1b8080903997574ab5a2508a14f780ce08aa4de050de 0b89b75cce8f2a415296e3b08fa707d53d90b2c75087c74c0266c186c81b428b ql/lib/codeql/swift/generated/expr/ConditionalCheckedCastExpr.qll 92a999dd1dcc1f498ed2e28b4d65ac697788960a66452a66b5281c287596d42b 92a999dd1dcc1f498ed2e28b4d65ac697788960a66452a66b5281c287596d42b -ql/lib/codeql/swift/generated/expr/ConstructorRefCallExpr.qll d0662d960b78c3cf7e81cf5b619aa9e2a906d35c094ae32702da96720354fe4f d0662d960b78c3cf7e81cf5b619aa9e2a906d35c094ae32702da96720354fe4f ql/lib/codeql/swift/generated/expr/CovariantFunctionConversionExpr.qll b749118590163eafbd538e71e4c903668451f52ae0dabbb13e504e7b1fefa9e1 abaf3f10d35bab1cf6ab44cb2e2eb1768938985ce00af4877d6043560a6b48ec ql/lib/codeql/swift/generated/expr/CovariantReturnConversionExpr.qll f1b409f0bf54b149deb1a40fbe337579a0f6eb2498ef176ef5f64bc53e94e2fe 532d6cb2ebbb1e6da4b26df439214a5a64ec1eb8a222917ba2913f4ee8d73bd8 ql/lib/codeql/swift/generated/expr/DeclRefExpr.qll eee2d4468f965e8e6a6727a3e04158de7f88731d2a2384a33e72e88b9e46a59a 54a91a444e5a0325cd69e70f5a58b8f7aa20aaa3d9b1451b97f491c109a1cd74 @@ -475,7 +473,7 @@ ql/lib/codeql/swift/generated/expr/DifferentiableFunctionExtractOriginalExpr.qll ql/lib/codeql/swift/generated/expr/DiscardAssignmentExpr.qll f2cb4a5295855bcfe47a223e0ab9b915c22081fe7dddda801b360aa365604efd f2cb4a5295855bcfe47a223e0ab9b915c22081fe7dddda801b360aa365604efd ql/lib/codeql/swift/generated/expr/DotSelfExpr.qll af32541b2a03d91c4b4184b8ebca50e2fe61307c2b438f50f46cd90592147425 af32541b2a03d91c4b4184b8ebca50e2fe61307c2b438f50f46cd90592147425 ql/lib/codeql/swift/generated/expr/DotSyntaxBaseIgnoredExpr.qll 12c9cf8d2fd3c5245e12f43520de8b7558d65407fa935da7014ac12de8d6887e 49f5f12aeb7430fa15430efd1193f56c7e236e87786e57fd49629bd61daa7981 -ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll 3768ef558b4fe8c2f0fb4db9b61f84999577a9a4ce5f97fa773a98bf367202ff 3768ef558b4fe8c2f0fb4db9b61f84999577a9a4ce5f97fa773a98bf367202ff +ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll 1eedcaafbf5e83b5e535f608ba29e25f0e0de7dbc484e14001362bad132c45d0 1eedcaafbf5e83b5e535f608ba29e25f0e0de7dbc484e14001362bad132c45d0 ql/lib/codeql/swift/generated/expr/DynamicLookupExpr.qll 0f0d745085364bca3b67f67e3445d530cbd3733d857c76acab2bccedabb5446e f252dd4b1ba1580fc9a32f42ab1b5be49b85120ec10c278083761494d1ee4c5d ql/lib/codeql/swift/generated/expr/DynamicMemberRefExpr.qll 2eab0e58a191624a9bf81a25f5ddad841f04001b7e9412a91e49b9d015259bbe 2eab0e58a191624a9bf81a25f5ddad841f04001b7e9412a91e49b9d015259bbe ql/lib/codeql/swift/generated/expr/DynamicSubscriptExpr.qll f9d7d2fc89f1b724cab837be23188604cefa2c368fa07e942c7a408c9e824f3d f9d7d2fc89f1b724cab837be23188604cefa2c368fa07e942c7a408c9e824f3d @@ -485,6 +483,7 @@ ql/lib/codeql/swift/generated/expr/ErasureExpr.qll c232bc7b612429b97dbd4bb2383c2 ql/lib/codeql/swift/generated/expr/ErrorExpr.qll 8e354eed5655e7261d939f3831eb6fa2961cdd2cebe41e3e3e7f54475e8a6083 8e354eed5655e7261d939f3831eb6fa2961cdd2cebe41e3e3e7f54475e8a6083 ql/lib/codeql/swift/generated/expr/ExistentialMetatypeToObjectExpr.qll eb0d42aac3f6331011a0e26cf5581c5e0a1b5523d2da94672abdebe70000d65b efe2bc0424e551454acc919abe4dac7fd246b84f1ae0e5d2e31a49cbcf84ce40 ql/lib/codeql/swift/generated/expr/ExplicitCastExpr.qll d98c1ad02175cfaad739870cf041fcd58143dd4b2675b632b68cda63855a4ceb 2aded243b54c1428ba16c0f131ab5e4480c2004002b1089d9186a435eb3a6ab5 +ql/lib/codeql/swift/generated/expr/ExplicitClosureExpr.qll c5291fb91e04a99133d1b4caf25f8bd6e7f2e7b9d5d99558143899f4dc9a7861 c5291fb91e04a99133d1b4caf25f8bd6e7f2e7b9d5d99558143899f4dc9a7861 ql/lib/codeql/swift/generated/expr/Expr.qll 68beba5a460429be58ba2dcad990932b791209405345fae35b975fe64444f07e a0a25a6870f8c9f129289cec7929aa3d6ec67e434919f3fb39dc060656bd1529 ql/lib/codeql/swift/generated/expr/FloatLiteralExpr.qll ae851773886b3d33ab5535572a4d6f771d4b11d6c93e802f01348edb2d80c454 35f103436fc2d1b2cec67b5fbae07b28c054c9687d57cbd3245c38c55d8bde0b ql/lib/codeql/swift/generated/expr/ForceTryExpr.qll 062997b5e9a9e993de703856ae6af60fe1950951cf77cdab11b972fb0a5a4ed3 062997b5e9a9e993de703856ae6af60fe1950951cf77cdab11b972fb0a5a4ed3 @@ -497,6 +496,7 @@ ql/lib/codeql/swift/generated/expr/IfExpr.qll d9ef7f9ee06f718fd7f244ca0d892e4b11 ql/lib/codeql/swift/generated/expr/ImplicitConversionExpr.qll 52dc57e4413ab523d2c2254ce6527d2d9adaaa4e7faba49b02a88df292aa911d 39883081b5feacf1c55ed99499a135c1da53cd175ab6a05a6969625c6247efd7 ql/lib/codeql/swift/generated/expr/InOutExpr.qll 26d2019105c38695bace614aa9552b901fa5580f463822688ee556b0e0832859 665333c422f6f34f134254cf2a48d3f5f441786517d0916ade5bec717a28d59d ql/lib/codeql/swift/generated/expr/InOutToPointerExpr.qll 4b9ceffe43f192fac0c428d66e6d91c3a6e2136b6d4e3c98cdab83b2e6a77719 4b9ceffe43f192fac0c428d66e6d91c3a6e2136b6d4e3c98cdab83b2e6a77719 +ql/lib/codeql/swift/generated/expr/InitializerRefCallExpr.qll 4556d49d78566ad70a5e784a6db4897dc78ef1f30e67f0052dbb070eca8350f0 4556d49d78566ad70a5e784a6db4897dc78ef1f30e67f0052dbb070eca8350f0 ql/lib/codeql/swift/generated/expr/InjectIntoOptionalExpr.qll b6fafb589901d73e94eb9bb0f5e87b54378d06ccc04c51a9f4c8003d1f23ead6 b6fafb589901d73e94eb9bb0f5e87b54378d06ccc04c51a9f4c8003d1f23ead6 ql/lib/codeql/swift/generated/expr/IntegerLiteralExpr.qll aa54660c47169a35e396ea44430c3c4ec4353e33df1a00bd82aff7119f5af71b 7ba90cf17dd34080a9923253986b0f2680b44c4a4ba6e0fbad8b39d3b20c44b9 ql/lib/codeql/swift/generated/expr/InterpolatedStringLiteralExpr.qll 35f79ec9d443165229a2aa4744551e9e288d5cd051ace48a24af96dc99e7184a 28e8a3dc8491bcb91827a6316f16540518b2f85a875c4a03501986730a468935 @@ -504,7 +504,7 @@ ql/lib/codeql/swift/generated/expr/IsExpr.qll b5ca50490cae8ac590b68a1a51b7039a54 ql/lib/codeql/swift/generated/expr/KeyPathApplicationExpr.qll 232e204a06b8fad3247040d47a1aa34c6736b764ab1ebca6c5dc74c3d4fc0c9b 6b823c483ee33cd6419f0a61a543cfce0cecfd0c90df72e60d01f5df8b3da3c0 ql/lib/codeql/swift/generated/expr/KeyPathDotExpr.qll ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878 ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878 ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll d78eb3a2805f7a98b23b8cb16aa66308e7a131284b4cd148a96e0b8c600e1db3 9f05ace69b0de3cdd9e9a1a6aafeb4478cd15423d2fa9e818dd049ddb2adfeb9 -ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll d8e93dcfa7fa8a00005f30b4aaa426f50d5040db11bef0c3b56558419b6cc110 3ca7d7ca9e52a025c38d7605c509d6758a4d5ceb0543192074c901f5935d4453 +ql/lib/codeql/swift/generated/expr/LazyInitializationExpr.qll b15d59017c4f763de1b944e0630f3f9aafced0114420c976afa98e8db613a695 71a10c48de9a74af880c95a71049b466851fe3cc18b4f7661952829eeb63d1ba ql/lib/codeql/swift/generated/expr/LinearFunctionExpr.qll cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7 cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7 ql/lib/codeql/swift/generated/expr/LinearFunctionExtractOriginalExpr.qll ee7d3e025815b5af392ffc006ec91e3150130f2bd708ab92dbe80f2efa9e6792 bcf9ed64cca2dcf5bb544f6347de3d6faa059a1900042a36555e11dfbe0a6013 ql/lib/codeql/swift/generated/expr/LinearToDifferentiableFunctionExpr.qll f7aa178bff083d8e2822fda63de201d9d7f56f7f59f797ec92826001fca98143 c3ef32483f6da294c066c66b1d40159bc51366d817cf64a364f375f5e5dfa8b0 @@ -518,14 +518,14 @@ ql/lib/codeql/swift/generated/expr/MetatypeConversionExpr.qll 714ecbc8ac51fdaaa4 ql/lib/codeql/swift/generated/expr/MethodLookupExpr.qll 357bc9ab24830ab60c1456c836e8449ce30ee67fe04e2f2e9437b3211b3b9757 687a3b3e6aeab2d4185f59fc001b3a69e83d96023b0589330a13eeefe3502a80 ql/lib/codeql/swift/generated/expr/NilLiteralExpr.qll 6f44106bc5396c87681676fc3e1239fe052d1a481d0a854afa8b66369668b058 6f44106bc5396c87681676fc3e1239fe052d1a481d0a854afa8b66369668b058 ql/lib/codeql/swift/generated/expr/NumberLiteralExpr.qll 8acc7df8fe83b7d36d66b2feed0b8859bfde873c6a88dd676c9ebed32f39bd04 4bbafc8996b2e95522d8167417668b536b2651817f732554de3083c4857af96a -ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll 8b4f7a9668d1cae4058ba460673b3e0b79f05f2fe871fd992ca1b7ea85f7c09d 629a3057c0ff3ede3a18ea8ea1aa29b24bc780d0dc60b51f99793a6001432a4e +ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll 6a4a36798deb602f4cf48c25da3d487e43efb93d7508e9fc2a4feceaa465df73 7f4b5b8a1adf68c23e169cd45a43436be1f30a15b93aabbf57b8fd64eadc2629 ql/lib/codeql/swift/generated/expr/ObjectLiteralExpr.qll 541bd1d9efd110a9e3334cd6849ad04f0e8408f1a72456a79d110f2473a8f87c 3c51d651e8d511b177b21c9ecb0189e4e7311c50abe7f57569be6b2fef5bc0d7 ql/lib/codeql/swift/generated/expr/OneWayExpr.qll bf6dbe9429634a59e831624dde3fe6d32842a543d25a8a5e5026899b7a608a54 dd2d844f3e4b190dfba123cf470a2c2fcfdcc0e02944468742abe816db13f6ba ql/lib/codeql/swift/generated/expr/OpaqueValueExpr.qll 354f23d00d5ea2e734fd192130620d26c76c14d5bb7b0a1aa69f17ffb5289793 354f23d00d5ea2e734fd192130620d26c76c14d5bb7b0a1aa69f17ffb5289793 ql/lib/codeql/swift/generated/expr/OpenExistentialExpr.qll 55cfe105f217a4bdb15d1392705030f1d7dec8c082cafa875301f81440ec0b7b 168389014cddb8fd738e2e84ddd22983e5c620c3c843de51976171038d95adc0 ql/lib/codeql/swift/generated/expr/OptionalEvaluationExpr.qll 000b00afe1dcdec43f756f699fd3e38212884eab14bf90e3c276d4ca9cb444a6 177bd4bfbb44e9f5aeaaf283b6537f3146900c1376854607827d224a81456f59 ql/lib/codeql/swift/generated/expr/OptionalTryExpr.qll f0c8dff90faee4fbf07772efda53afe1acc1fd148c16ee4d85a1502a36178e71 f0c8dff90faee4fbf07772efda53afe1acc1fd148c16ee4d85a1502a36178e71 -ql/lib/codeql/swift/generated/expr/OtherConstructorDeclRefExpr.qll c77bf23292e9c8a151ef6baf667a06a2b6a57d05b0bd0a09177522ce5b8c7c33 011d84d72d82ad318697f8af035807a87af5745d5ec9c1ad32a0af9531f8c79e +ql/lib/codeql/swift/generated/expr/OtherInitializerRefExpr.qll bfaa8c29fcc356c76839400dbf996e2f39af1c8fe77f2df422a4d71cbb3b8aa3 23f67902b58f79ba19b645411756567cc832b164c7f4efcc77319987c9266d5f ql/lib/codeql/swift/generated/expr/OverloadedDeclRefExpr.qll 355f2c3c8f23345198ebfffba24e5b465ebdf6cd1ae44290bd211536377a6256 9436286072c690dff1229cddf6837d50704e8d4f1c710803495580cab37a0a1b ql/lib/codeql/swift/generated/expr/ParenExpr.qll f3fb35017423ee7360cab737249c01623cafc5affe8845f3898697d3bd2ef9d7 f3fb35017423ee7360cab737249c01623cafc5affe8845f3898697d3bd2ef9d7 ql/lib/codeql/swift/generated/expr/PointerToPointerExpr.qll 7d6fa806bba09804705f9cef5be66e09cbbbbda9a4c5eae75d4380f1527bb1bd 7d6fa806bba09804705f9cef5be66e09cbbbbda9a4c5eae75d4380f1527bb1bd @@ -533,7 +533,7 @@ ql/lib/codeql/swift/generated/expr/PostfixUnaryExpr.qll d1094c42aa03158bf89bace0 ql/lib/codeql/swift/generated/expr/PrefixUnaryExpr.qll f66dee3c70ed257914de4dd4e8501bb49c9fe6c156ddad86cdcc636cf49b5f62 f66dee3c70ed257914de4dd4e8501bb49c9fe6c156ddad86cdcc636cf49b5f62 ql/lib/codeql/swift/generated/expr/PropertyWrapperValuePlaceholderExpr.qll 011897278a75050f1c55bd3f2378b73b447d5882404fd410c9707cd06d226a0e e4878e3193b8abf7df6f06676d576e1886fd9cd19721583dd66ea67429bc72a1 ql/lib/codeql/swift/generated/expr/ProtocolMetatypeToObjectExpr.qll b692be6e5b249c095b77f4adcad5760f48bc07f6f53767ee3d236025ee4a2a51 efa47435cde494f3477164c540ac1ce0b036cb9c60f5f8ec7bfca82a88e208fb -ql/lib/codeql/swift/generated/expr/RebindSelfInConstructorExpr.qll 7796a88c1635b3bd2492563880c995f1a7a0c68f69bad33b8bd77086eb1ce404 aee11e030ba21115931cbc1e34ac001eaafe4460fb3724a078aa4cbda84e4642 +ql/lib/codeql/swift/generated/expr/RebindSelfInInitializerExpr.qll 7e4420bfe346ccc94e7ec9e0c61e7885fa5ad66cca24dc772583350d1fd256e1 62888a035ef882e85173bb9d57bce5e95d6fd6763ceb4067abf1d60468983501 ql/lib/codeql/swift/generated/expr/RegexLiteralExpr.qll a11eb6f6ce7cebb35ab9ff51eae85f272980140814d7e6bded454069457a1312 bdb4bb65c9f4e187cf743ed13c0213bb7e55db9cc3adeae2169df5e32b003940 ql/lib/codeql/swift/generated/expr/SelfApplyExpr.qll 8a2d8ee8d0006a519aadbdb9055cfb58a28fd2837f4e3641b357e3b6bda0febe fc64b664b041e57f9ca10d94c59e9723a18d4ff9d70f2389f4c11a2a9f903a6f ql/lib/codeql/swift/generated/expr/SequenceExpr.qll 45f976cbc3ce6b3278955a76a55cd0769e69f9bd16e84b40888cd8ebda6be917 ebb090897e4cc4371383aa6771163f73fa2c28f91e6b5f4eed42d7ad018267f3 @@ -668,14 +668,14 @@ ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscript ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql b7a60a79a6368f410298d6a00c9ccefae47875c540b668a924ebb37d331564a5 798760446f64d552669c87c5c377d41dcdbcbcdbcc20f9c4b58bd15248e3fb0b ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql 5c017af7e6b16ee68990eec12affe81eb114338bac4d445f4b231fe0f110eccc db86c828a892b0acd150a780914e7e48c280cad473d3680a453bdee03aee1e9d -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql 1d42eb1a5b832cfaf1949b61a01a6a11448a6d4369a44f2511bb31d1d7fc10a8 b326a6743121353f8a66410d3d9151ca969939abcbbe5c411872ca290da45123 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql 17f9903978c9a8fc607d970532270090cea030ff57c2f6699c37672707ce5c70 cdd7ce47691a84aa5402a8946d4027f7b9dbce930057dfd62c14b470a5710cb0 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.ql 8648679e9403477c7f97b6df450a0fa623dc9aff0777021ee33f9cc96eef2611 59c384c35804bf205c3c63e8b956e6bc89d3ded7952911c40e7bf156acb56bf8 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.ql 826f3cd3a3737938ade950555a36506d970894c3c761c07d36f0a6252672e9bc 0e681a49e07b69bf0df10c14864da946b04b2dea2412bdc93c9b5567c77f819a -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.ql a8f7b6cbb8ab43ed612cfbb36b48b5d6dd23b1dbe94a99d95fedf80e3c95f89f d70eb32403c4983c58448fe5c9e2d88bc873ab61e0e310c38356a9a144b42978 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.ql 7c61c15d75f681c5f5817bdc1e0c1e2594afdc43a5a8889bd385b6cd007d6509 7f6111069c3f289fb3bd21933893757a0adbf8be8f21bf5f8960b6fb26840219 -ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.ql 0d773ccd4c84a5280f03341cccff8363479b668541d269311215db866a1cfd53 743d584a8d5d85aa11e96ca44151f1239c750bf8a429d60269129696411a0294 +ql/test/extractor-tests/generated/decl/Accessor/Accessor.ql 8fb08071a437da7a161c987feacfe56d424a88159b39f705abfb1273f830d70b b816cdf9dffa8149fc9747cc0c863275680e435149744176334395600bcb0b95 +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.ql ed8bb0bb96160439dbd22744b6ec0cd9b9bbb0b55eafe4656148e1f7f860eeb3 4660c0f6e58811a1bd6ce98dfc453d9b7b00f5da32cfe0fb1f9d5ff24c4897ac +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.ql b12a0a2fd5a53810cc1ccf0b4b42af46cc9e2b1dd3bb5489d569a715ee6231da cc9f6df05e3ad95f061f78ed9877a5296c17ff384a45ec71032ab63a866e173c +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.ql e1fc97033e0d37f482562be5ebee2f7e37c26512f82a1dcd16ca9d4be2ca335f 19fa5d21e709ee59f2a6560a61f579e09ee90bbbf971ac70857a555965057057 +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.ql d0b6260b9d63e11fd202c612b2e5ed623457ffe53710dc5cbfa8f26f0ff16da3 770c480a389bc5d7c915d5f4d38c672615c0b17cc134508de519da7f794806da +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.ql d01afe57e4161131b4fafb9fad59fc6d0f6220802ff178f433a913d903d9fc49 c9dbae26272c008d1b9ae5fc83d0958c657e9baed8c5e87cb4782ffa7684c382 +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.ql 818a352cf9ee3a9b0592f8b668e0ca540e3ee4351004d38323ca8d95e04630a1 ca8b5b7cdbd5c7c4eab30bdb7dcfb60e7c59deb5d37a8b021b36fb0f5efec79c +ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.ql 260ce6a4fc2a650826a5c372fa1df63d28112623a1671189ea5f44c0d8d45bc2 6f45476da7cf37d450c07ab9651e12f928e104ba6d7f4bf173a265b9b72c89eb ql/test/extractor-tests/generated/decl/AssociatedTypeDecl/AssociatedTypeDecl.ql 74579a1907817168b5014ebcb69ab9a85687189c73145f1a7c2d4b334af4eb30 5d1f265f0e6c1d2392a9e37a42a8e184a16e473836c1a45b5dbc4daccc4aeabb ql/test/extractor-tests/generated/decl/AssociatedTypeDecl/AssociatedTypeDecl_getBaseType.ql 39d26252c242eec5aaef23951bd76755a4d3cdceff7349b15067fefb2ece14b3 214fdbaa77d32ee6f21bcccf112d46c9d26006552081cc1f90cbb00a527a9d7f ql/test/extractor-tests/generated/decl/AssociatedTypeDecl/AssociatedTypeDecl_getMember.ql e662e651d84bddcf49445d7bf5732d0dad30242d32b90f86e40de0010d48fd9c a6b7028468490a12c0a9f4c535cbd5e6c50a6c3519c9d2552d34f9411f904718 @@ -685,16 +685,8 @@ ql/test/extractor-tests/generated/decl/ClassDecl/ClassDecl.ql a76c9710142c368206 ql/test/extractor-tests/generated/decl/ClassDecl/ClassDecl_getBaseType.ql 5f4fddbb3fb3d003f1485dc4c5a56f7d0d26dfc1d691540085654c4c66e70e69 0b5a5b757ca92e664ef136d26ac682aa5a0e071494d9f09d85f66cd13807e81d ql/test/extractor-tests/generated/decl/ClassDecl/ClassDecl_getGenericTypeParam.ql ca0b73a4f31eea47def7a1de017de36b5fdaec96ae98edb03ff00611bfcac572 f9badd62887a30113484496532b3ff9b67ff5047eb5a311aa2ec2e4d91321e0e ql/test/extractor-tests/generated/decl/ClassDecl/ClassDecl_getMember.ql f73881b14bb4eaf83dacf60b9e46d440227f90566e2dfb8908a55567626ccdda f78a7261f7ccfe01ca55f7279bd5a1a302fc65ba36b13e779426d173c7465b84 -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.ql 97813e8d28abdafa300278a7bdef824ca2cf62b0677e31cb7293f2063ffe69de c3c5f8784d1a0f4f38b691cec5b870587ae1c6587d4862681a9bc6ce10ffa73f -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.ql 3c742b9c8d8d8c23d1bef03f559e1b91f0d3848084ba5819f118c323dd1920a2 340d4e4a6312ffaf4c47bbc753828c1e478d84a2d399c66220288c081c8357ca -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.ql d3fe4c473661944cd3868ee5c2ef9cc7e7da0b414c4b4f7018456b1a4ee44c02 491a3271a4e15c99d5a8b9429a07c63bbf2e311ac2e72604d3118163ba309ba9 -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.ql b5e64bf02a5991a1549794af0aaab9ae654c88b5d52a3e04b7ac525b3a64af5e 034a7d0bf7500afa952a28d184d1d073e71c3dcec3bc26fcefaed70aef9de3ce -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.ql aaba9cb097602d761c48de09de059ef2fe112e0c6c64a5f6988a95cddc9155d8 6e6b76a51bd1d9d4ec25865a1c229e5859ca55f11639ccee414a8cac7de1662a -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.ql d80c7dfdde294264b6763a7129e666efd98111dbf203a9739c24942659d7f832 396e44281e4f4af2188a4f7d246872b7058132b12f508b88dc60d5bdd14e2092 -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.ql 392bc906a24a432b0dd65a18248cab53874e1ea018b44fdf07d8acb55939c85d cf272febc8355d7171308c0b35f65ae0469106c022093f87ffd25d5951eef4a3 -ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.ql c8a593149db6785d9bc7017a3fcee305832ab434955b4c36ac2842e214f0acac b70a7c18085961d2c907631d69811071deb391c45c94ef7165bf7ce700dabaf9 -ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql 57a1bd716499550f7f578f2fc9243537fc54b034eece623fb37b761785cee808 0945ed19a9f4558755bb3ea7666b0a617333c339e759d49759fc8bfefe4dc2fc -ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.ql 7f1890b891402c7974087bd1621ce7ce2893008a2ab0218396c82e99ce2e6c9d 4d483e18ad2211759e3a57f973679844d28505b84fe2b10b2303a561d0ac7ca5 +ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql 66c20b9245c7f6aa6dabb81e00717a3441ea02176aed2b63e35aa7828d4282cc 4fd1cee669d972dc7295f5640985868e74f570e4ced8750793afb8fa889f438e +ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.ql 22ed8e1f4c57fae2e39087837380f359d6e0c478ce6af272bcaddab2e55beb26 8b1248b8d1da45992ec8d926d0cd2a77eb43f667c41469227b6ea2b60196d94a ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAttachedPropertyWrapperType.ql 0fd114f752aae89ef80bc80e0532aa4849106f6d1af40b1861e4ba191898b69e fdf28e036a1c4dcb0a3aaaa9fb96dcc755ff530ab6f252270c319df9a1d0d7ac ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getMember.ql ab8061f4c024d4c4ea3f39211ccfadf9216968b7d8b9bf2dd813dea6b0250586 973bf8a0bcfcf98108267dd89fe9eb658a6096c9462881716f5a6ad260217a97 ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getParentInitializer.ql c90aa3ae4249af7d436f976773e9208b41d784b57c6d73e23e1993f01262f592 3b1391d6b0605011bec7cc6f3f964ed476273bd5ed4bb5d6590f862aa4e7a2a3 @@ -703,8 +695,7 @@ ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getProper ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperBackingVarBinding.ql addbf4e32d383fc35b7505a33c5a675feeedd708c4b94ce8fc89c5bc88c36f1f 549c8ec9cf2c1dc6881e848af8be9900d54604a747ded1f04bd5cadf93e5ede3 ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperProjectionVar.ql 502a76b34c78d3cf8f38969671840dc9e28d478ba7afe671963145ba4dc9460d 6125a91820b6b8d139392c32478383e52e40e572e0f92a32f0e513409d2c4e11 ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getPropertyWrapperProjectionVarBinding.ql 40274aac8b67cb6a285bf91ccdc725ae1556b13ebcc6854a43e759b029733687 44e569aac32148bcce4cd5e8ebb33d7418580b7f5f03dfbd18635db9965b28d9 -ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/Deinitializer/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/EnumCaseDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl.ql e1906b751a4b72081a61b175e016f5182fdd0e27518f16017d17e14c65dd4268 8a1dd50e951ed2c25f18823ff8b9ab36dc2dc49703801dd48da443bc384bd9b4 ql/test/extractor-tests/generated/decl/EnumDecl/EnumDecl_getBaseType.ql 4ace6176a57dd4c759356ddbefc28b25481c80bdeddfeb396d91b07db55af22a d0d1337ccbba45a648fe68fefc51006e14506d4fb7211fb2bde45f7761c4dbf1 @@ -724,18 +715,27 @@ ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getDeclaration.ql a ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getImportedModule.ql 0339867ca4f414cceba85df20d12eca64a3eea9847bb02829dc28fa95701e987 8c292768f56cecbdfeb92985212e6b39ecada819891921c3ba1532d88d84c43e ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getMember.ql 6d48d3a93bc96dba3bda71ec9d9d6282615c2228a58da6167c169fafaedb3e17 8560b23d0f52b845c81727ce09c0b2f9647965c83d7de165e8cd3d91be5bdd42 ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/decl/Initializer/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.ql f9216e83077ebc0cb5a5bf2d7368af86167a1bfd378f9cd5592fd484a1bbc5dd 1c2de61cb064474340db10de4399c49f15eb0a5669e6dc9587d8b4f656b0134f ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql 321619519c5cffefda78f11f2c85a199af76fccbfcc51126c7a558ba12fdfd80 30e48eb820ba9d7f3ec30bf4536c0f84280c5f2ca8c63427f6b77d74a092e68b ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql 65fae5b1a7db3a11fd837ed78c663e8907306c36695ae73e4e29559755276fbe 3ddef1a7af7a636e66674fadb3e727ad18655a9ecb4c73fd3d6aca202f1191fb ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getBaseType.ql 54a4bd2cfa666271ae9092285bb7217b082c88483d614066cfb599fc8ab84305 8b24ab8e93efe3922cb192eb5de5f517763058782e83e8732153421adddd68e1 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getMember.ql a4663d47cf0a16a07167b9a64d56f8ba8e504a78142c7e216d1df69879df9130 3f6a4080e33bddd1e34fa25519d855811c256182055db4989be8150fcddd541b +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.ql a56ea8bf7080ba76cee7a1fca2b3e63f09d644663c15e405c8a62ee9506335d3 3b18f5200b09ccbe3087c57d30a50169fc84241a76c406e2b090cf8d214e5596 +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.ql 91688f59415c479a7e39f61eeccbac09a4fe3fcfdd94f198d7bdbef39ccc892c 760497101fd872d513641b810cae91ff9e436f3c20f4c31b72d36c2d49492ef9 +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.ql 886ba37f06245ad27d0cdfcd40841af7e833115be60088238f3228f959f38b4a 5fa4f55ecf42b83386e7280372032c542852d24ff21633264a79a176a3409f81 +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.ql 7ffd1471731291cc7a4d6d2b53af68ce0376ccaf1e8e64c4e30d83f43358ed6d da8811b63c608cd7270ce047571ec9646e1483d50f51ee113acf2f3564932790 +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.ql f44e526e4a2ef4dab9e2979bbbc51ae47ad25999b83636ede9836e0f0b920ef4 0fd66c5fd368329c61b7ca4aaa36b4c71d4e71d25f517d94ffb094d2e593bcbf +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.ql c7cf5b81a8db16ef44c84eb861d4a7f41ce2b9ad733f8853b66d6dc64ed315a3 8000fad2b9b56077e8a262ec2899d765026bd07836622b0cb48327e6d6e9c0a0 +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.ql ae3ba8026861c4f79e1810457331e838790cbf11537d1b1e2ba38bf3fea5a7cd 10e7c69956784f01e3455d29cd934358347afd4317cf08e12e0385559eb4fd1f +ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.ql d7d05f91e9ef0c083780b9215e761efc753dbef98789bd7d21c5e40fce322826 ec8e6262e15730532e12dcb6faaf24b10bc5a2c7b0e1ec97fe1d5ed047b1994d ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl.ql 16ccca5a90cc3133ab085ccb843416abc103f2fcf3423a84fbd7f5c15a5c7f17 242d7ea07842ee3fb0f9905b5cbc0ea744f1116c4591c5f133025260991bfdeb ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl_getBaseType.ql d030fd55ea5a5443c03e8ba1a024c03e3c68c96c948c850131f59fbac6409402 46816c1a75a4cf11db95884733382e46d5573b6c1116d5de0bfe5ae91fed4c3d ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl_getGenericTypeParam.ql c147420a91c157ee37a900dd7739bdb386fba5eeaadd84e609d2642d3fdbf2e0 cf1c981b6cb7b84944e9430cfe361905dcc396d4356d7f20a0ba993352bd5b02 ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl_getMember.ql aa601966925c03f066624f4297b01ccc21cfeaba8e803e29c42cc9ef954258b6 4559e1d5257dcfb6cf414538f57fc015e483c06381048066c28b31324a2db09c ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl_getOpaqueGenericParam.ql 2b4264a68817f53ddd73e4fd80e9f7c3a5fcfa4d0692135e2d3b10c8a8379d98 c2efac460b655e726d898b2b80cbfce24820a922e26935804ddd21ae9c474085 -ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql 5cd8b94d6c0d2fa7ecc554d4231ca6e9fc19524d33ebc4c551dbb5f89e77bc11 509f3bac1ed171d81c848de994403f3eeed3636f780c3bef2e45263e0497b571 -ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.ql bf6bd41b1eedad87a2d86acb4b183ddbd150119a0301ec56c6d7129fe5dee453 247fe28adde08cb86e03f9f21c32ea96b8bdc522b848bb84a592292338cac6b1 +ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql 44e04f4d8753f19be04200f6a6fe5f5e8ed77c1a7c4026ae0ff640878ec19650 2a4d994754aa0560d12c15ff39bbc4b7d83116e7b4a9ea46f432a6a267a661de +ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.ql a29956d6876079a4062ff48fc4475f9718cfb545cb6252cfa1423e8872666d03 a048d661ad1c23e02fb6c441d7cca78dd773432c08800e06d392469c64952163 ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAttachedPropertyWrapperType.ql 3642cfd3ecf47a6b81a1745dc043131df349b898a937445eadfdee9f69aec3fc 97137c6673c45b0743db310b0839426eab71f5bc80ccc7bab99c304b8198159f ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getMember.ql b811867588bd320b9dcd116451a173c40581b36ba40b1ecb2da57033967d50df 523c22740e366edb880706fd11adcb1aaaa81509090bd2d0f0265ec5d2b431c2 ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getParentInitializer.ql f0ecd0352a7e34e13040f31440a6170b0661b625c65b35d13021731b6db0f441 9fc89925050c9538ba3ba0b8c45278e30dffba64b53002f675e3f7a9ef014539 @@ -768,12 +768,8 @@ ql/test/extractor-tests/generated/expr/BindOptionalExpr/MISSING_SOURCE.txt 66846 ql/test/extractor-tests/generated/expr/BooleanLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/CallExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/CaptureListExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/CoerceExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ConditionalCheckedCastExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.ql 0214077b52ed4c152c70bbd0347c7340d42e584954fba5242f1380e357ec79a0 f8ce48428247f8616c15d39198bf8b3857f1acca12a800bcc912c34720f5f039 -ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql a3a01f99aa8df3aafed50cc7828829e567e01fed7874854e7a620904f1641fc9 962669b36b9adbc3d75bae79a9a754692c20d6e14ee2b47aca8f3f93b27895da -ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql c3504dda8c41ebc386a9011deb06b0f5312538306b5ca10f7c4ff2e0f2c277dd aa6785ac86fe4954ef679fdfa6cd91f964d9281ab0162240b6e4b9eb67b0eda3 ql/test/extractor-tests/generated/expr/DeclRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/DefaultArgumentExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/DictionaryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 @@ -788,6 +784,7 @@ ql/test/extractor-tests/generated/expr/DynamicLookupExpr/DynamicLookupExpr_getTy ql/test/extractor-tests/generated/expr/DynamicTypeExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/EnumIsCaseExpr/EnumIsCaseExpr.ql 9a4505f330e014769509be594299bcaa046d0a2c9a8ce4ac3a1d6d6b050af317 92c8392ded3fb26af7434b8aae34b1649b4c808acafc3adbd8ecb60ada5f6e72 ql/test/extractor-tests/generated/expr/EnumIsCaseExpr/EnumIsCaseExpr_getType.ql edc2e175c971465f5667c4586bc4c77e5c245d267f80009a049b8f657238a5f4 5df26b5bdf975ba910a7c3446705c3ac82a67d05565d860fe58464ee82bafdde +ql/test/extractor-tests/generated/expr/ExplicitClosureExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/FloatLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ForceTryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/ForceValueExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 @@ -798,6 +795,9 @@ ql/test/extractor-tests/generated/expr/IfExpr/MISSING_SOURCE.txt 66846d526b0bc43 ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.ql 7ffb80368c4d80adccaa0267cc76b42b76304d5d485286f82e22ae51776812f3 51b38032cb3d392be56fa8bdf53379a174cf3de39d4bf6b730c611ae3ab7cec8 ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.ql 184ff1dec5d65024c8a0c2b316706ac58c68c62c715c266211e947168750c89a 486fc8d65c0db86bdada2d540f665278caab43454a69ccc8c2e702729397fef0 ql/test/extractor-tests/generated/expr/InOutExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.ql b9fa70b73983f8b2b61669fb1cd5993d81cf679e3b03085c9c291cde459f9eec 6bd70ac2b43a35d7925d9eb156b8063f7e30535eeeaa669b289c8256ef4ccf80 +ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.ql a5ce633986488b8b3aafe593f71ffffe413adb94201a2099f05806d94a5a456b 2a7e25c0141d84b364b8f17cf5d8fa19cf48b690ebbbd773c7a061ab66e16dd4 +ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.ql f913bc92d5b225a2da441ea7c1b8c1ffc24273c25a779dc861bf6eaf87ed00fc a36a4a963c1969f801b9bc96686aad64e303bb8ac02025249eda02a4eae84431 ql/test/extractor-tests/generated/expr/IntegerLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 @@ -807,7 +807,7 @@ ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql 3eddbfac203a76 ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql ce38c747737e13f80a212576ae943f0a770fc87a15dabcb0d730515aeb530a3f a50138c47e61e9eab4131a03e1b3e065ed0fca1452c6a3d4f8f48a6124d445be ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql 61d8d0f50c62e6bdf98005609861f6f4fd16e59c439706abf03ba27f87ed3cb1 403ee884bb83b7a4207993afbda7964e676f5f64923ce11e65a0cf8bd199e01d ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql 992497671107be454ffe1f42b513a5bca37bd31849587ad55f6bd87d8ac5d4a7 b51109f0d9e5e6238d8ab9e67f24d435a873a7884308c4f01ec4ecad51ed031d -ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/LazyInitializationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/MemberRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 @@ -823,7 +823,7 @@ ql/test/extractor-tests/generated/expr/OpaqueValueExpr/MISSING_SOURCE.txt 66846d ql/test/extractor-tests/generated/expr/OpenExistentialExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/OptionalEvaluationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/OptionalTryExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 -ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/OtherInitializerRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr.ql 7687a79d05efbbae7ce68780cb946cb500ed79c5e03aa0f3c132d0b98b6efe80 f23082710afb2bc247acab84b669540664461f0ec04a946125f17586640dfba8 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr_getArgument.ql 3b0e6f81599e5565bb78aff753932776c933fefdc8dc49e57db9f5b4164017f6 43031a3d0baa58f69b89a8a5d69f1a40ffeeaddc8a630d241e107de63ea54532 ql/test/extractor-tests/generated/expr/PostfixUnaryExpr/PostfixUnaryExpr_getType.ql fa909883140fe89084c289c18ebc681402c38d0f37159d01f043f62de80521fc 4cd748e201e9374e589eaa0e3cc10310a1378bba15272a327d5cf54dbd526e8f @@ -831,7 +831,7 @@ ql/test/extractor-tests/generated/expr/PrefixUnaryExpr/MISSING_SOURCE.txt 66846d ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr.ql 9ac73f157d11e4ee1c47dceaadd2f686893da6557e4e600c62edad90db2eb92d bf353009ee1b6127350d976f2e869b615d54b998e59664bdb25ea8d6ab5b132d ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getType.ql 0972415a8ac29f460d480990f85c3976ad947e26510da447bbf74ee61d9b3f4e 463b8ce871911b99c495ea84669b4e6f8eafc645df483f6a99413e930bc0275e ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getWrappedValue.ql 208153f062b04bec13a860b64ea51c1d531597140d81a6d4598294dc9f8649a2 dfaea19e1075c02dfc0366fac8fd2edfae8dde06308730eb462c54be5b571129 -ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 +ql/test/extractor-tests/generated/expr/RebindSelfInInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 diff --git a/swift/ql/lib/codeql/swift/elements.qll b/swift/ql/lib/codeql/swift/elements.qll index 50561d6f706..7c75c11c976 100644 --- a/swift/ql/lib/codeql/swift/elements.qll +++ b/swift/ql/lib/codeql/swift/elements.qll @@ -18,31 +18,30 @@ import codeql.swift.elements.PlatformVersionAvailabilitySpec import codeql.swift.elements.UnknownFile import codeql.swift.elements.UnknownLocation import codeql.swift.elements.UnspecifiedElement -import codeql.swift.elements.decl.AbstractFunctionDecl import codeql.swift.elements.decl.AbstractStorageDecl import codeql.swift.elements.decl.AbstractTypeParamDecl -import codeql.swift.elements.decl.AccessorDecl +import codeql.swift.elements.decl.Accessor import codeql.swift.elements.decl.AssociatedTypeDecl import codeql.swift.elements.decl.CapturedDecl import codeql.swift.elements.decl.ClassDecl -import codeql.swift.elements.decl.ConcreteFuncDecl import codeql.swift.elements.decl.ConcreteVarDecl -import codeql.swift.elements.decl.ConstructorDecl import codeql.swift.elements.decl.Decl -import codeql.swift.elements.decl.DestructorDecl +import codeql.swift.elements.decl.Deinitializer import codeql.swift.elements.decl.EnumCaseDecl import codeql.swift.elements.decl.EnumDecl import codeql.swift.elements.decl.EnumElementDecl import codeql.swift.elements.decl.ExtensionDecl -import codeql.swift.elements.decl.FuncDecl +import codeql.swift.elements.decl.Function import codeql.swift.elements.decl.GenericContext import codeql.swift.elements.decl.GenericTypeDecl import codeql.swift.elements.decl.GenericTypeParamDecl import codeql.swift.elements.decl.IfConfigDecl import codeql.swift.elements.decl.ImportDecl import codeql.swift.elements.decl.InfixOperatorDecl +import codeql.swift.elements.decl.Initializer import codeql.swift.elements.decl.MissingMemberDecl import codeql.swift.elements.decl.ModuleDecl +import codeql.swift.elements.decl.NamedFunction import codeql.swift.elements.decl.NominalTypeDecl import codeql.swift.elements.decl.OpaqueTypeDecl import codeql.swift.elements.decl.OperatorDecl @@ -61,7 +60,6 @@ import codeql.swift.elements.decl.TypeDecl import codeql.swift.elements.decl.ValueDecl import codeql.swift.elements.decl.VarDecl import codeql.swift.elements.expr.AbiSafeConversionExpr -import codeql.swift.elements.expr.AbstractClosureExpr import codeql.swift.elements.expr.AnyHashableErasureExpr import codeql.swift.elements.expr.AnyTryExpr import codeql.swift.elements.expr.AppliedPropertyWrapperExpr @@ -89,7 +87,6 @@ import codeql.swift.elements.expr.CollectionExpr import codeql.swift.elements.expr.CollectionUpcastConversionExpr import codeql.swift.elements.expr.ConditionalBridgeFromObjCExpr import codeql.swift.elements.expr.ConditionalCheckedCastExpr -import codeql.swift.elements.expr.ConstructorRefCallExpr import codeql.swift.elements.expr.CovariantFunctionConversionExpr import codeql.swift.elements.expr.CovariantReturnConversionExpr import codeql.swift.elements.expr.DeclRefExpr @@ -102,7 +99,6 @@ import codeql.swift.elements.expr.DifferentiableFunctionExtractOriginalExpr import codeql.swift.elements.expr.DiscardAssignmentExpr import codeql.swift.elements.expr.DotSelfExpr import codeql.swift.elements.expr.DotSyntaxBaseIgnoredExpr -import codeql.swift.elements.expr.DotSyntaxCallExpr import codeql.swift.elements.expr.DynamicLookupExpr import codeql.swift.elements.expr.DynamicMemberRefExpr import codeql.swift.elements.expr.DynamicSubscriptExpr @@ -112,6 +108,7 @@ import codeql.swift.elements.expr.ErasureExpr import codeql.swift.elements.expr.ErrorExpr import codeql.swift.elements.expr.ExistentialMetatypeToObjectExpr import codeql.swift.elements.expr.ExplicitCastExpr +import codeql.swift.elements.expr.ExplicitClosureExpr import codeql.swift.elements.expr.Expr import codeql.swift.elements.expr.FloatLiteralExpr import codeql.swift.elements.expr.ForceTryExpr @@ -131,7 +128,7 @@ import codeql.swift.elements.expr.IsExpr import codeql.swift.elements.expr.KeyPathApplicationExpr import codeql.swift.elements.expr.KeyPathDotExpr import codeql.swift.elements.expr.KeyPathExpr -import codeql.swift.elements.expr.LazyInitializerExpr +import codeql.swift.elements.expr.LazyInitializationExpr import codeql.swift.elements.expr.LinearFunctionExpr import codeql.swift.elements.expr.LinearFunctionExtractOriginalExpr import codeql.swift.elements.expr.LinearToDifferentiableFunctionExpr @@ -152,7 +149,7 @@ import codeql.swift.elements.expr.OpaqueValueExpr import codeql.swift.elements.expr.OpenExistentialExpr import codeql.swift.elements.expr.OptionalEvaluationExpr import codeql.swift.elements.expr.OptionalTryExpr -import codeql.swift.elements.expr.OtherConstructorDeclRefExpr +import codeql.swift.elements.expr.OtherInitializerRefExpr import codeql.swift.elements.expr.OverloadedDeclRefExpr import codeql.swift.elements.expr.ParenExpr import codeql.swift.elements.expr.PointerToPointerExpr @@ -160,7 +157,7 @@ import codeql.swift.elements.expr.PostfixUnaryExpr import codeql.swift.elements.expr.PrefixUnaryExpr import codeql.swift.elements.expr.PropertyWrapperValuePlaceholderExpr import codeql.swift.elements.expr.ProtocolMetatypeToObjectExpr -import codeql.swift.elements.expr.RebindSelfInConstructorExpr +import codeql.swift.elements.expr.RebindSelfInInitializerExpr import codeql.swift.elements.expr.RegexLiteralExpr import codeql.swift.elements.expr.SequenceExpr import codeql.swift.elements.expr.StringLiteralExpr diff --git a/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll deleted file mode 100644 index c394898d4bd..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll +++ /dev/null @@ -1,16 +0,0 @@ -private import codeql.swift.generated.decl.AbstractFunctionDecl -private import codeql.swift.elements.decl.MethodDecl - -/** - * A function. - */ -class AbstractFunctionDecl extends Generated::AbstractFunctionDecl, Callable { - override string toString() { result = this.getName() } -} - -/** - * A free (non-member) function. - */ -class FreeFunctionDecl extends AbstractFunctionDecl { - FreeFunctionDecl() { not this instanceof MethodDecl } -} diff --git a/swift/ql/lib/codeql/swift/elements/expr/ClosureExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/decl/AccessorConstructor.qll similarity index 67% rename from swift/ql/lib/codeql/swift/elements/expr/ClosureExprConstructor.qll rename to swift/ql/lib/codeql/swift/elements/decl/AccessorConstructor.qll index 09bd0f2d629..39f8546bcf3 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/ClosureExprConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/AccessorConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructClosureExpr(Raw::ClosureExpr id) { any() } +predicate constructAccessor(Raw::Accessor id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll deleted file mode 100644 index 4879a1e47fd..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll +++ /dev/null @@ -1,40 +0,0 @@ -private import codeql.swift.generated.decl.AccessorDecl - -private predicate isKnownAccessorKind(AccessorDecl decl, string kind) { - decl.isGetter() and kind = "get" - or - decl.isSetter() and kind = "set" - or - decl.isWillSet() and kind = "willSet" - or - decl.isDidSet() and kind = "didSet" - or - decl.isRead() and kind = "_read" - or - decl.isModify() and kind = "_modify" - or - decl.isUnsafeAddress() and kind = "unsafeAddress" - or - decl.isUnsafeMutableAddress() and kind = "unsafeMutableAddress" -} - -class AccessorDecl extends Generated::AccessorDecl { - predicate isPropertyObserver() { - this instanceof WillSetObserver or this instanceof DidSetObserver - } - - override string toString() { - isKnownAccessorKind(this, result) - or - not isKnownAccessorKind(this, _) and - result = super.toString() - } -} - -class WillSetObserver extends AccessorDecl { - WillSetObserver() { this.isWillSet() } -} - -class DidSetObserver extends AccessorDecl { - DidSetObserver() { this.isDidSet() } -} diff --git a/swift/ql/lib/codeql/swift/elements/decl/AccessorOrNamedFunction.qll b/swift/ql/lib/codeql/swift/elements/decl/AccessorOrNamedFunction.qll new file mode 100644 index 00000000000..9964b079ba1 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/AccessorOrNamedFunction.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.decl.AccessorOrNamedFunction + +class AccessorOrNamedFunction extends Generated::AccessorOrNamedFunction { } diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll deleted file mode 100644 index b3f71701748..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDecl.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.decl.ConcreteFuncDecl - -class ConcreteFuncDecl extends Generated::ConcreteFuncDecl { } diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll deleted file mode 100644 index 8cb6843744c..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll +++ /dev/null @@ -1,17 +0,0 @@ -private import codeql.swift.generated.decl.ConstructorDecl -private import codeql.swift.elements.decl.MethodDecl -private import codeql.swift.elements.type.FunctionType -private import codeql.swift.elements.type.OptionalType - -/** - * An initializer of a class, struct, enum or protocol. - */ -class ConstructorDecl extends Generated::ConstructorDecl, MethodDecl { - override string toString() { result = this.getSelfParam().getType() + "." + super.toString() } - - /** Holds if this initializer returns an optional type. Failable initializers are written as `init?`. */ - predicate isFailable() { - this.getInterfaceType().(FunctionType).getResult().(FunctionType).getResult() instanceof - OptionalType - } -} diff --git a/swift/ql/lib/codeql/swift/elements/decl/DestructorDeclConstructor.qll b/swift/ql/lib/codeql/swift/elements/decl/DeinitializerConstructor.qll similarity index 65% rename from swift/ql/lib/codeql/swift/elements/decl/DestructorDeclConstructor.qll rename to swift/ql/lib/codeql/swift/elements/decl/DeinitializerConstructor.qll index e28ed48ba9d..2e839ec2292 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/DestructorDeclConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/DeinitializerConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructDestructorDecl(Raw::DestructorDecl id) { any() } +predicate constructDeinitializer(Raw::Deinitializer id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll deleted file mode 100644 index 9c7077a03b8..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll +++ /dev/null @@ -1,9 +0,0 @@ -private import codeql.swift.generated.decl.DestructorDecl -private import codeql.swift.elements.decl.MethodDecl - -/** - * A deinitializer of a class. - */ -class DestructorDecl extends Generated::DestructorDecl, MethodDecl { - override string toString() { result = this.getSelfParam().getType() + "." + super.toString() } -} diff --git a/swift/ql/lib/codeql/swift/elements/decl/FuncDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/FuncDecl.qll deleted file mode 100644 index 194f61138f7..00000000000 --- a/swift/ql/lib/codeql/swift/elements/decl/FuncDecl.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.decl.FuncDecl - -class FuncDecl extends Generated::FuncDecl { } diff --git a/swift/ql/lib/codeql/swift/elements/decl/AccessorDeclConstructor.qll b/swift/ql/lib/codeql/swift/elements/decl/InitializerConstructor.qll similarity index 66% rename from swift/ql/lib/codeql/swift/elements/decl/AccessorDeclConstructor.qll rename to swift/ql/lib/codeql/swift/elements/decl/InitializerConstructor.qll index 11d033586cc..d07bbf5b381 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/AccessorDeclConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/InitializerConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructAccessorDecl(Raw::AccessorDecl id) { any() } +predicate constructInitializer(Raw::Initializer id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/decl/NamedFunction.qll b/swift/ql/lib/codeql/swift/elements/decl/NamedFunction.qll new file mode 100644 index 00000000000..203326b342c --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/NamedFunction.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.decl.NamedFunction + +class NamedFunction extends Generated::NamedFunction { } diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDeclConstructor.qll b/swift/ql/lib/codeql/swift/elements/decl/NamedFunctionConstructor.qll similarity index 64% rename from swift/ql/lib/codeql/swift/elements/decl/ConstructorDeclConstructor.qll rename to swift/ql/lib/codeql/swift/elements/decl/NamedFunctionConstructor.qll index 27838e1f944..c8bb3b3a55f 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDeclConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/NamedFunctionConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructConstructorDecl(Raw::ConstructorDecl id) { any() } +predicate constructNamedFunction(Raw::NamedFunction id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll deleted file mode 100644 index 72ab22a9053..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/AbstractClosureExpr.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.expr.AbstractClosureExpr - -class AbstractClosureExpr extends Generated::AbstractClosureExpr { } diff --git a/swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll deleted file mode 100644 index 206d61b062e..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExpr.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.expr.ConstructorRefCallExpr - -class ConstructorRefCallExpr extends Generated::ConstructorRefCallExpr { } diff --git a/swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll new file mode 100644 index 00000000000..a326c7814d6 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.expr.ExplicitClosureExpr + +class ExplicitClosureExpr extends Generated::ExplicitClosureExpr { } diff --git a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll similarity index 69% rename from swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExprConstructor.qll rename to swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll index 2af5c1c2302..1cd4624d577 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExprConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructLazyInitializerExpr(Raw::LazyInitializerExpr id) { any() } +predicate constructExplicitClosureExpr(Raw::ExplicitClosureExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExpr.qll new file mode 100644 index 00000000000..02dc288ca23 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExpr.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.expr.InitializerRefCallExpr + +class InitializerRefCallExpr extends Generated::InitializerRefCallExpr { } diff --git a/swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExprConstructor.qll similarity index 50% rename from swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExprConstructor.qll rename to swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExprConstructor.qll index 153381f2178..f76011502fb 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/ConstructorRefCallExprConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/InitializerRefCallExprConstructor.qll @@ -1,3 +1,3 @@ private import codeql.swift.generated.Raw -predicate constructConstructorRefCallExpr(Raw::ConstructorRefCallExpr id) { none() } +predicate constructInitializerRefCallExpr(Raw::InitializerRefCallExpr id) { none() } diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDeclConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExprConstructor.qll similarity index 60% rename from swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDeclConstructor.qll rename to swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExprConstructor.qll index 09ff9fc3f71..8fb49806c28 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/ConcreteFuncDeclConstructor.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExprConstructor.qll @@ -1,4 +1,4 @@ // generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.Raw -predicate constructConcreteFuncDecl(Raw::ConcreteFuncDecl id) { any() } +predicate constructLazyInitializationExpr(Raw::LazyInitializationExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll deleted file mode 100644 index 31622166944..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -private import codeql.swift.generated.expr.LazyInitializerExpr - -class LazyInitializerExpr extends Generated::LazyInitializerExpr { - override string toString() { result = this.getSubExpr().toString() } -} diff --git a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll deleted file mode 100644 index b8fcee3f8d0..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -private import codeql.swift.generated.expr.OtherConstructorDeclRefExpr - -class OtherConstructorDeclRefExpr extends Generated::OtherConstructorDeclRefExpr { - override string toString() { result = this.getConstructorDecl().toString() } -} diff --git a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll deleted file mode 100644 index 5080a5375e4..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExprConstructor.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.Raw - -predicate constructOtherConstructorDeclRefExpr(Raw::OtherConstructorDeclRefExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExprConstructor.qll new file mode 100644 index 00000000000..90d1b7507d9 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExprConstructor.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.Raw + +predicate constructOtherInitializerRefExpr(Raw::OtherInitializerRefExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll deleted file mode 100644 index 17eefdac6c4..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -private import codeql.swift.generated.expr.RebindSelfInConstructorExpr - -class RebindSelfInConstructorExpr extends Generated::RebindSelfInConstructorExpr { - override string toString() { result = "self = ..." } -} diff --git a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll deleted file mode 100644 index 06a6714dcab..00000000000 --- a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExprConstructor.qll +++ /dev/null @@ -1,4 +0,0 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file -private import codeql.swift.generated.Raw - -predicate constructRebindSelfInConstructorExpr(Raw::RebindSelfInConstructorExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExprConstructor.qll new file mode 100644 index 00000000000..46bb3c8c2ef --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExprConstructor.qll @@ -0,0 +1,4 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +private import codeql.swift.generated.Raw + +predicate constructRebindSelfInInitializerExpr(Raw::RebindSelfInInitializerExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 93277d2587b..270a7398843 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -1,5 +1,8 @@ // generated by codegen/codegen.py import codeql.swift.elements +import codeql.swift.elements.decl.AccessorOrNamedFunction +import codeql.swift.elements.expr.DotSyntaxCallExpr +import codeql.swift.elements.expr.InitializerRefCallExpr import codeql.swift.elements.expr.SelfApplyExpr private module Impl { @@ -519,46 +522,21 @@ private module Impl { ) } - private Element getImmediateChildOfAbstractFunctionDecl( - AbstractFunctionDecl e, int index, string partialPredicateCall - ) { - exists(int b, int bGenericContext, int bValueDecl, int bCallable, int n | - b = 0 and - bGenericContext = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and - bValueDecl = - bGenericContext + 1 + - max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and - bCallable = - bValueDecl + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and - n = bCallable and - ( - none() - or - result = getImmediateChildOfGenericContext(e, index - b, partialPredicateCall) - or - result = getImmediateChildOfValueDecl(e, index - bGenericContext, partialPredicateCall) - or - result = getImmediateChildOfCallable(e, index - bValueDecl, partialPredicateCall) - ) - ) - } - private Element getImmediateChildOfAbstractStorageDecl( AbstractStorageDecl e, int index, string partialPredicateCall ) { - exists(int b, int bValueDecl, int n, int nAccessorDecl | + exists(int b, int bValueDecl, int n, int nAccessor | b = 0 and bValueDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and n = bValueDecl and - nAccessorDecl = n + 1 + max(int i | i = -1 or exists(e.getImmediateAccessorDecl(i)) | i) and + nAccessor = n + 1 + max(int i | i = -1 or exists(e.getImmediateAccessor(i)) | i) and ( none() or result = getImmediateChildOfValueDecl(e, index - b, partialPredicateCall) or - result = e.getImmediateAccessorDecl(index - n) and - partialPredicateCall = "AccessorDecl(" + (index - n).toString() + ")" + result = e.getImmediateAccessor(index - n) and + partialPredicateCall = "Accessor(" + (index - n).toString() + ")" ) ) } @@ -582,6 +560,29 @@ private module Impl { ) } + private Element getImmediateChildOfFunction(Function e, int index, string partialPredicateCall) { + exists(int b, int bGenericContext, int bValueDecl, int bCallable, int n | + b = 0 and + bGenericContext = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and + bValueDecl = + bGenericContext + 1 + + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and + bCallable = + bValueDecl + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and + n = bCallable and + ( + none() + or + result = getImmediateChildOfGenericContext(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfValueDecl(e, index - bGenericContext, partialPredicateCall) + or + result = getImmediateChildOfCallable(e, index - bValueDecl, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfInfixOperatorDecl( InfixOperatorDecl e, int index, string partialPredicateCall ) { @@ -658,48 +659,32 @@ private module Impl { ) } - private Element getImmediateChildOfConstructorDecl( - ConstructorDecl e, int index, string partialPredicateCall + private Element getImmediateChildOfAccessorOrNamedFunction( + AccessorOrNamedFunction e, int index, string partialPredicateCall ) { - exists(int b, int bAbstractFunctionDecl, int n | + exists(int b, int bFunction, int n | b = 0 and - bAbstractFunctionDecl = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and - n = bAbstractFunctionDecl and + bFunction = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFunction(e, i, _)) | i) and + n = bFunction and ( none() or - result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) + result = getImmediateChildOfFunction(e, index - b, partialPredicateCall) ) ) } - private Element getImmediateChildOfDestructorDecl( - DestructorDecl e, int index, string partialPredicateCall + private Element getImmediateChildOfDeinitializer( + Deinitializer e, int index, string partialPredicateCall ) { - exists(int b, int bAbstractFunctionDecl, int n | + exists(int b, int bFunction, int n | b = 0 and - bAbstractFunctionDecl = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and - n = bAbstractFunctionDecl and + bFunction = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFunction(e, i, _)) | i) and + n = bFunction and ( none() or - result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) - ) - ) - } - - private Element getImmediateChildOfFuncDecl(FuncDecl e, int index, string partialPredicateCall) { - exists(int b, int bAbstractFunctionDecl, int n | - b = 0 and - bAbstractFunctionDecl = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and - n = bAbstractFunctionDecl and - ( - none() - or - result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) + result = getImmediateChildOfFunction(e, index - b, partialPredicateCall) ) ) } @@ -725,6 +710,21 @@ private module Impl { ) } + private Element getImmediateChildOfInitializer( + Initializer e, int index, string partialPredicateCall + ) { + exists(int b, int bFunction, int n | + b = 0 and + bFunction = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFunction(e, i, _)) | i) and + n = bFunction and + ( + none() + or + result = getImmediateChildOfFunction(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfModuleDecl(ModuleDecl e, int index, string partialPredicateCall) { exists(int b, int bTypeDecl, int n | b = 0 and @@ -802,17 +802,17 @@ private module Impl { ) } - private Element getImmediateChildOfAccessorDecl( - AccessorDecl e, int index, string partialPredicateCall - ) { - exists(int b, int bFuncDecl, int n | + private Element getImmediateChildOfAccessor(Accessor e, int index, string partialPredicateCall) { + exists(int b, int bAccessorOrNamedFunction, int n | b = 0 and - bFuncDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFuncDecl(e, i, _)) | i) and - n = bFuncDecl and + bAccessorOrNamedFunction = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfAccessorOrNamedFunction(e, i, _)) | i) and + n = bAccessorOrNamedFunction and ( none() or - result = getImmediateChildOfFuncDecl(e, index - b, partialPredicateCall) + result = getImmediateChildOfAccessorOrNamedFunction(e, index - b, partialPredicateCall) ) ) } @@ -833,21 +833,6 @@ private module Impl { ) } - private Element getImmediateChildOfConcreteFuncDecl( - ConcreteFuncDecl e, int index, string partialPredicateCall - ) { - exists(int b, int bFuncDecl, int n | - b = 0 and - bFuncDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFuncDecl(e, i, _)) | i) and - n = bFuncDecl and - ( - none() - or - result = getImmediateChildOfFuncDecl(e, index - b, partialPredicateCall) - ) - ) - } - private Element getImmediateChildOfConcreteVarDecl( ConcreteVarDecl e, int index, string partialPredicateCall ) { @@ -879,6 +864,23 @@ private module Impl { ) } + private Element getImmediateChildOfNamedFunction( + NamedFunction e, int index, string partialPredicateCall + ) { + exists(int b, int bAccessorOrNamedFunction, int n | + b = 0 and + bAccessorOrNamedFunction = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfAccessorOrNamedFunction(e, i, _)) | i) and + n = bAccessorOrNamedFunction and + ( + none() + or + result = getImmediateChildOfAccessorOrNamedFunction(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfNominalTypeDecl( NominalTypeDecl e, int index, string partialPredicateCall ) { @@ -1040,25 +1042,6 @@ private module Impl { ) } - private Element getImmediateChildOfAbstractClosureExpr( - AbstractClosureExpr e, int index, string partialPredicateCall - ) { - exists(int b, int bExpr, int bCallable, int n | - b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - bCallable = - bExpr + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and - n = bCallable and - ( - none() - or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) - or - result = getImmediateChildOfCallable(e, index - bExpr, partialPredicateCall) - ) - ) - } - private Element getImmediateChildOfAnyTryExpr(AnyTryExpr e, int index, string partialPredicateCall) { exists(int b, int bExpr, int n, int nSubExpr | b = 0 and @@ -1174,6 +1157,25 @@ private module Impl { ) } + private Element getImmediateChildOfClosureExpr( + ClosureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int bCallable, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + bCallable = + bExpr + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and + n = bCallable and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfCallable(e, index - bExpr, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfCollectionExpr( CollectionExpr e, int index, string partialPredicateCall ) { @@ -1482,8 +1484,8 @@ private module Impl { ) } - private Element getImmediateChildOfLazyInitializerExpr( - LazyInitializerExpr e, int index, string partialPredicateCall + private Element getImmediateChildOfLazyInitializationExpr( + LazyInitializationExpr e, int index, string partialPredicateCall ) { exists(int b, int bExpr, int n, int nSubExpr | b = 0 and @@ -1656,8 +1658,8 @@ private module Impl { ) } - private Element getImmediateChildOfOtherConstructorDeclRefExpr( - OtherConstructorDeclRefExpr e, int index, string partialPredicateCall + private Element getImmediateChildOfOtherInitializerRefExpr( + OtherInitializerRefExpr e, int index, string partialPredicateCall ) { exists(int b, int bExpr, int n | b = 0 and @@ -1705,8 +1707,8 @@ private module Impl { ) } - private Element getImmediateChildOfRebindSelfInConstructorExpr( - RebindSelfInConstructorExpr e, int index, string partialPredicateCall + private Element getImmediateChildOfRebindSelfInInitializerExpr( + RebindSelfInInitializerExpr e, int index, string partialPredicateCall ) { exists(int b, int bExpr, int n, int nSubExpr | b = 0 and @@ -2038,15 +2040,15 @@ private module Impl { private Element getImmediateChildOfAutoClosureExpr( AutoClosureExpr e, int index, string partialPredicateCall ) { - exists(int b, int bAbstractClosureExpr, int n | + exists(int b, int bClosureExpr, int n | b = 0 and - bAbstractClosureExpr = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractClosureExpr(e, i, _)) | i) and - n = bAbstractClosureExpr and + bClosureExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfClosureExpr(e, i, _)) | i) and + n = bClosureExpr and ( none() or - result = getImmediateChildOfAbstractClosureExpr(e, index - b, partialPredicateCall) + result = getImmediateChildOfClosureExpr(e, index - b, partialPredicateCall) ) ) } @@ -2174,22 +2176,6 @@ private module Impl { ) } - private Element getImmediateChildOfClosureExpr( - ClosureExpr e, int index, string partialPredicateCall - ) { - exists(int b, int bAbstractClosureExpr, int n | - b = 0 and - bAbstractClosureExpr = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractClosureExpr(e, i, _)) | i) and - n = bAbstractClosureExpr and - ( - none() - or - result = getImmediateChildOfAbstractClosureExpr(e, index - b, partialPredicateCall) - ) - ) - } - private Element getImmediateChildOfCoerceExpr(CoerceExpr e, int index, string partialPredicateCall) { exists(int b, int bExplicitCastExpr, int n | b = 0 and @@ -2426,6 +2412,22 @@ private module Impl { ) } + private Element getImmediateChildOfExplicitClosureExpr( + ExplicitClosureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bClosureExpr, int n | + b = 0 and + bClosureExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfClosureExpr(e, i, _)) | i) and + n = bClosureExpr and + ( + none() + or + result = getImmediateChildOfClosureExpr(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfForceTryExpr( ForceTryExpr e, int index, string partialPredicateCall ) { @@ -2984,22 +2986,6 @@ private module Impl { ) } - private Element getImmediateChildOfConstructorRefCallExpr( - ConstructorRefCallExpr e, int index, string partialPredicateCall - ) { - exists(int b, int bSelfApplyExpr, int n | - b = 0 and - bSelfApplyExpr = - b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSelfApplyExpr(e, i, _)) | i) and - n = bSelfApplyExpr and - ( - none() - or - result = getImmediateChildOfSelfApplyExpr(e, index - b, partialPredicateCall) - ) - ) - } - private Element getImmediateChildOfDotSyntaxCallExpr( DotSyntaxCallExpr e, int index, string partialPredicateCall ) { @@ -3064,6 +3050,22 @@ private module Impl { ) } + private Element getImmediateChildOfInitializerRefCallExpr( + InitializerRefCallExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bSelfApplyExpr, int n | + b = 0 and + bSelfApplyExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSelfApplyExpr(e, i, _)) | i) and + n = bSelfApplyExpr and + ( + none() + or + result = getImmediateChildOfSelfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfIsExpr(IsExpr e, int index, string partialPredicateCall) { exists(int b, int bCheckedCastExpr, int n | b = 0 and @@ -4885,24 +4887,24 @@ private module Impl { or result = getImmediateChildOfPrefixOperatorDecl(e, index, partialAccessor) or - result = getImmediateChildOfConstructorDecl(e, index, partialAccessor) + result = getImmediateChildOfDeinitializer(e, index, partialAccessor) or - result = getImmediateChildOfDestructorDecl(e, index, partialAccessor) + result = getImmediateChildOfInitializer(e, index, partialAccessor) or result = getImmediateChildOfModuleDecl(e, index, partialAccessor) or result = getImmediateChildOfSubscriptDecl(e, index, partialAccessor) or - result = getImmediateChildOfAccessorDecl(e, index, partialAccessor) + result = getImmediateChildOfAccessor(e, index, partialAccessor) or result = getImmediateChildOfAssociatedTypeDecl(e, index, partialAccessor) or - result = getImmediateChildOfConcreteFuncDecl(e, index, partialAccessor) - or result = getImmediateChildOfConcreteVarDecl(e, index, partialAccessor) or result = getImmediateChildOfGenericTypeParamDecl(e, index, partialAccessor) or + result = getImmediateChildOfNamedFunction(e, index, partialAccessor) + or result = getImmediateChildOfOpaqueTypeDecl(e, index, partialAccessor) or result = getImmediateChildOfParamDecl(e, index, partialAccessor) @@ -4953,7 +4955,7 @@ private module Impl { or result = getImmediateChildOfKeyPathExpr(e, index, partialAccessor) or - result = getImmediateChildOfLazyInitializerExpr(e, index, partialAccessor) + result = getImmediateChildOfLazyInitializationExpr(e, index, partialAccessor) or result = getImmediateChildOfMakeTemporarilyEscapableExpr(e, index, partialAccessor) or @@ -4967,13 +4969,13 @@ private module Impl { or result = getImmediateChildOfOptionalEvaluationExpr(e, index, partialAccessor) or - result = getImmediateChildOfOtherConstructorDeclRefExpr(e, index, partialAccessor) + result = getImmediateChildOfOtherInitializerRefExpr(e, index, partialAccessor) or result = getImmediateChildOfOverloadedDeclRefExpr(e, index, partialAccessor) or result = getImmediateChildOfPropertyWrapperValuePlaceholderExpr(e, index, partialAccessor) or - result = getImmediateChildOfRebindSelfInConstructorExpr(e, index, partialAccessor) + result = getImmediateChildOfRebindSelfInInitializerExpr(e, index, partialAccessor) or result = getImmediateChildOfSequenceExpr(e, index, partialAccessor) or @@ -5023,8 +5025,6 @@ private module Impl { or result = getImmediateChildOfClassMetatypeToObjectExpr(e, index, partialAccessor) or - result = getImmediateChildOfClosureExpr(e, index, partialAccessor) - or result = getImmediateChildOfCoerceExpr(e, index, partialAccessor) or result = getImmediateChildOfCollectionUpcastConversionExpr(e, index, partialAccessor) @@ -5051,6 +5051,8 @@ private module Impl { or result = getImmediateChildOfExistentialMetatypeToObjectExpr(e, index, partialAccessor) or + result = getImmediateChildOfExplicitClosureExpr(e, index, partialAccessor) + or result = getImmediateChildOfForceTryExpr(e, index, partialAccessor) or result = getImmediateChildOfForeignObjectConversionExpr(e, index, partialAccessor) @@ -5113,8 +5115,6 @@ private module Impl { or result = getImmediateChildOfConditionalCheckedCastExpr(e, index, partialAccessor) or - result = getImmediateChildOfConstructorRefCallExpr(e, index, partialAccessor) - or result = getImmediateChildOfDotSyntaxCallExpr(e, index, partialAccessor) or result = getImmediateChildOfDynamicMemberRefExpr(e, index, partialAccessor) @@ -5123,6 +5123,8 @@ private module Impl { or result = getImmediateChildOfForcedCheckedCastExpr(e, index, partialAccessor) or + result = getImmediateChildOfInitializerRefCallExpr(e, index, partialAccessor) + or result = getImmediateChildOfIsExpr(e, index, partialAccessor) or result = getImmediateChildOfMagicIdentifierLiteralExpr(e, index, partialAccessor) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 7a13a82dbcd..dc5ddeed979 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -500,22 +500,14 @@ module Raw { Type getInterfaceType() { value_decls(this, result) } } - /** - * INTERNAL: Do not use. - */ - class AbstractFunctionDecl extends @abstract_function_decl, GenericContext, ValueDecl, Callable { - } - /** * INTERNAL: Do not use. */ class AbstractStorageDecl extends @abstract_storage_decl, ValueDecl { /** - * Gets the `index`th accessor declaration of this abstract storage declaration (0-based). + * Gets the `index`th accessor of this abstract storage declaration (0-based). */ - AccessorDecl getAccessorDecl(int index) { - abstract_storage_decl_accessor_decls(this, index, result) - } + Accessor getAccessor(int index) { abstract_storage_decl_accessors(this, index, result) } } /** @@ -535,6 +527,11 @@ module Raw { ParamDecl getParam(int index) { enum_element_decl_params(this, index, result) } } + /** + * INTERNAL: Do not use. + */ + class Function extends @function, GenericContext, ValueDecl, Callable { } + /** * INTERNAL: Do not use. */ @@ -584,27 +581,27 @@ module Raw { /** * INTERNAL: Do not use. */ - class ConstructorDecl extends @constructor_decl, AbstractFunctionDecl { - override string toString() { result = "ConstructorDecl" } - } + class AccessorOrNamedFunction extends @accessor_or_named_function, Function { } /** * INTERNAL: Do not use. */ - class DestructorDecl extends @destructor_decl, AbstractFunctionDecl { - override string toString() { result = "DestructorDecl" } + class Deinitializer extends @deinitializer, Function { + override string toString() { result = "Deinitializer" } } - /** - * INTERNAL: Do not use. - */ - class FuncDecl extends @func_decl, AbstractFunctionDecl { } - /** * INTERNAL: Do not use. */ class GenericTypeDecl extends @generic_type_decl, GenericContext, TypeDecl { } + /** + * INTERNAL: Do not use. + */ + class Initializer extends @initializer, Function { + override string toString() { result = "Initializer" } + } + /** * INTERNAL: Do not use. */ @@ -770,48 +767,48 @@ module Raw { /** * INTERNAL: Do not use. */ - class AccessorDecl extends @accessor_decl, FuncDecl { - override string toString() { result = "AccessorDecl" } + class Accessor extends @accessor, AccessorOrNamedFunction { + override string toString() { result = "Accessor" } /** * Holds if this accessor is a getter. */ - predicate isGetter() { accessor_decl_is_getter(this) } + predicate isGetter() { accessor_is_getter(this) } /** * Holds if this accessor is a setter. */ - predicate isSetter() { accessor_decl_is_setter(this) } + predicate isSetter() { accessor_is_setter(this) } /** * Holds if this accessor is a `willSet`, called before the property is set. */ - predicate isWillSet() { accessor_decl_is_will_set(this) } + predicate isWillSet() { accessor_is_will_set(this) } /** * Holds if this accessor is a `didSet`, called after the property is set. */ - predicate isDidSet() { accessor_decl_is_did_set(this) } + predicate isDidSet() { accessor_is_did_set(this) } /** * Holds if this accessor is a `_read` coroutine, yielding a borrowed value of the property. */ - predicate isRead() { accessor_decl_is_read(this) } + predicate isRead() { accessor_is_read(this) } /** * Holds if this accessor is a `_modify` coroutine, yielding an inout value of the property. */ - predicate isModify() { accessor_decl_is_modify(this) } + predicate isModify() { accessor_is_modify(this) } /** * Holds if this accessor is an `unsafeAddress` immutable addressor. */ - predicate isUnsafeAddress() { accessor_decl_is_unsafe_address(this) } + predicate isUnsafeAddress() { accessor_is_unsafe_address(this) } /** * Holds if this accessor is an `unsafeMutableAddress` mutable addressor. */ - predicate isUnsafeMutableAddress() { accessor_decl_is_unsafe_mutable_address(this) } + predicate isUnsafeMutableAddress() { accessor_is_unsafe_mutable_address(this) } } /** @@ -821,13 +818,6 @@ module Raw { override string toString() { result = "AssociatedTypeDecl" } } - /** - * INTERNAL: Do not use. - */ - class ConcreteFuncDecl extends @concrete_func_decl, FuncDecl { - override string toString() { result = "ConcreteFuncDecl" } - } - /** * INTERNAL: Do not use. */ @@ -849,6 +839,13 @@ module Raw { override string toString() { result = "GenericTypeParamDecl" } } + /** + * INTERNAL: Do not use. + */ + class NamedFunction extends @named_function, AccessorOrNamedFunction { + override string toString() { result = "NamedFunction" } + } + /** * INTERNAL: Do not use. */ @@ -996,11 +993,6 @@ module Raw { Type getType() { expr_types(this, result) } } - /** - * INTERNAL: Do not use. - */ - class AbstractClosureExpr extends @abstract_closure_expr, Expr, Callable { } - /** * INTERNAL: Do not use. */ @@ -1098,9 +1090,14 @@ module Raw { /** * Gets the closure body of this capture list expression. */ - ClosureExpr getClosureBody() { capture_list_exprs(this, result) } + ExplicitClosureExpr getClosureBody() { capture_list_exprs(this, result) } } + /** + * INTERNAL: Do not use. + */ + class ClosureExpr extends @closure_expr, Expr, Callable { } + /** * INTERNAL: Do not use. */ @@ -1348,13 +1345,13 @@ module Raw { /** * INTERNAL: Do not use. */ - class LazyInitializerExpr extends @lazy_initializer_expr, Expr { - override string toString() { result = "LazyInitializerExpr" } + class LazyInitializationExpr extends @lazy_initialization_expr, Expr { + override string toString() { result = "LazyInitializationExpr" } /** - * Gets the sub expression of this lazy initializer expression. + * Gets the sub expression of this lazy initialization expression. */ - Expr getSubExpr() { lazy_initializer_exprs(this, result) } + Expr getSubExpr() { lazy_initialization_exprs(this, result) } } /** @@ -1413,7 +1410,7 @@ module Raw { /** * Gets the method of this obj c selector expression. */ - AbstractFunctionDecl getMethod() { obj_c_selector_exprs(this, _, result) } + Function getMethod() { obj_c_selector_exprs(this, _, result) } } /** @@ -1472,13 +1469,13 @@ module Raw { /** * INTERNAL: Do not use. */ - class OtherConstructorDeclRefExpr extends @other_constructor_decl_ref_expr, Expr { - override string toString() { result = "OtherConstructorDeclRefExpr" } + class OtherInitializerRefExpr extends @other_initializer_ref_expr, Expr { + override string toString() { result = "OtherInitializerRefExpr" } /** - * Gets the constructor declaration of this other constructor declaration reference expression. + * Gets the initializer of this other initializer reference expression. */ - ConstructorDecl getConstructorDecl() { other_constructor_decl_ref_exprs(this, result) } + Initializer getInitializer() { other_initializer_ref_exprs(this, result) } } /** @@ -1519,18 +1516,18 @@ module Raw { /** * INTERNAL: Do not use. */ - class RebindSelfInConstructorExpr extends @rebind_self_in_constructor_expr, Expr { - override string toString() { result = "RebindSelfInConstructorExpr" } + class RebindSelfInInitializerExpr extends @rebind_self_in_initializer_expr, Expr { + override string toString() { result = "RebindSelfInInitializerExpr" } /** - * Gets the sub expression of this rebind self in constructor expression. + * Gets the sub expression of this rebind self in initializer expression. */ - Expr getSubExpr() { rebind_self_in_constructor_exprs(this, result, _) } + Expr getSubExpr() { rebind_self_in_initializer_exprs(this, result, _) } /** - * Gets the self of this rebind self in constructor expression. + * Gets the self of this rebind self in initializer expression. */ - VarDecl getSelf() { rebind_self_in_constructor_exprs(this, _, result) } + VarDecl getSelf() { rebind_self_in_initializer_exprs(this, _, result) } } /** @@ -1740,7 +1737,7 @@ module Raw { /** * INTERNAL: Do not use. */ - class AutoClosureExpr extends @auto_closure_expr, AbstractClosureExpr { + class AutoClosureExpr extends @auto_closure_expr, ClosureExpr { override string toString() { result = "AutoClosureExpr" } } @@ -1796,13 +1793,6 @@ module Raw { override string toString() { result = "ClassMetatypeToObjectExpr" } } - /** - * INTERNAL: Do not use. - */ - class ClosureExpr extends @closure_expr, AbstractClosureExpr { - override string toString() { result = "ClosureExpr" } - } - /** * INTERNAL: Do not use. */ @@ -1916,6 +1906,13 @@ module Raw { override string toString() { result = "ExistentialMetatypeToObjectExpr" } } + /** + * INTERNAL: Do not use. + */ + class ExplicitClosureExpr extends @explicit_closure_expr, ClosureExpr { + override string toString() { result = "ExplicitClosureExpr" } + } + /** * INTERNAL: Do not use. */ @@ -2258,13 +2255,6 @@ module Raw { override string toString() { result = "ConditionalCheckedCastExpr" } } - /** - * INTERNAL: Do not use. - */ - class ConstructorRefCallExpr extends @constructor_ref_call_expr, SelfApplyExpr { - override string toString() { result = "ConstructorRefCallExpr" } - } - /** * INTERNAL: Do not use. */ @@ -2293,6 +2283,13 @@ module Raw { override string toString() { result = "ForcedCheckedCastExpr" } } + /** + * INTERNAL: Do not use. + */ + class InitializerRefCallExpr extends @initializer_ref_call_expr, SelfApplyExpr { + override string toString() { result = "InitializerRefCallExpr" } + } + /** * INTERNAL: Do not use. */ diff --git a/swift/ql/lib/codeql/swift/generated/Synth.qll b/swift/ql/lib/codeql/swift/generated/Synth.qll index 78077f37c16..fdbadffcd33 100644 --- a/swift/ql/lib/codeql/swift/generated/Synth.qll +++ b/swift/ql/lib/codeql/swift/generated/Synth.qll @@ -64,7 +64,7 @@ module Synth { /** * INTERNAL: Do not use. */ - TAccessorDecl(Raw::AccessorDecl id) { constructAccessorDecl(id) } or + TAccessor(Raw::Accessor id) { constructAccessor(id) } or /** * INTERNAL: Do not use. */ @@ -77,10 +77,6 @@ module Synth { * INTERNAL: Do not use. */ TClassDecl(Raw::ClassDecl id) { constructClassDecl(id) } or - /** - * INTERNAL: Do not use. - */ - TConcreteFuncDecl(Raw::ConcreteFuncDecl id) { constructConcreteFuncDecl(id) } or /** * INTERNAL: Do not use. */ @@ -88,11 +84,7 @@ module Synth { /** * INTERNAL: Do not use. */ - TConstructorDecl(Raw::ConstructorDecl id) { constructConstructorDecl(id) } or - /** - * INTERNAL: Do not use. - */ - TDestructorDecl(Raw::DestructorDecl id) { constructDestructorDecl(id) } or + TDeinitializer(Raw::Deinitializer id) { constructDeinitializer(id) } or /** * INTERNAL: Do not use. */ @@ -125,6 +117,10 @@ module Synth { * INTERNAL: Do not use. */ TInfixOperatorDecl(Raw::InfixOperatorDecl id) { constructInfixOperatorDecl(id) } or + /** + * INTERNAL: Do not use. + */ + TInitializer(Raw::Initializer id) { constructInitializer(id) } or /** * INTERNAL: Do not use. */ @@ -133,6 +129,10 @@ module Synth { * INTERNAL: Do not use. */ TModuleDecl(Raw::ModuleDecl id) { constructModuleDecl(id) } or + /** + * INTERNAL: Do not use. + */ + TNamedFunction(Raw::NamedFunction id) { constructNamedFunction(id) } or /** * INTERNAL: Do not use. */ @@ -257,10 +257,6 @@ module Synth { TClassMetatypeToObjectExpr(Raw::ClassMetatypeToObjectExpr id) { constructClassMetatypeToObjectExpr(id) } or - /** - * INTERNAL: Do not use. - */ - TClosureExpr(Raw::ClosureExpr id) { constructClosureExpr(id) } or /** * INTERNAL: Do not use. */ @@ -283,10 +279,6 @@ module Synth { TConditionalCheckedCastExpr(Raw::ConditionalCheckedCastExpr id) { constructConditionalCheckedCastExpr(id) } or - /** - * INTERNAL: Do not use. - */ - TConstructorRefCallExpr(Raw::ConstructorRefCallExpr id) { constructConstructorRefCallExpr(id) } or /** * INTERNAL: Do not use. */ @@ -379,6 +371,10 @@ module Synth { TExistentialMetatypeToObjectExpr(Raw::ExistentialMetatypeToObjectExpr id) { constructExistentialMetatypeToObjectExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TExplicitClosureExpr(Raw::ExplicitClosureExpr id) { constructExplicitClosureExpr(id) } or /** * INTERNAL: Do not use. */ @@ -417,6 +413,10 @@ module Synth { * INTERNAL: Do not use. */ TInOutToPointerExpr(Raw::InOutToPointerExpr id) { constructInOutToPointerExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TInitializerRefCallExpr(Raw::InitializerRefCallExpr id) { constructInitializerRefCallExpr(id) } or /** * INTERNAL: Do not use. */ @@ -450,7 +450,7 @@ module Synth { /** * INTERNAL: Do not use. */ - TLazyInitializerExpr(Raw::LazyInitializerExpr id) { constructLazyInitializerExpr(id) } or + TLazyInitializationExpr(Raw::LazyInitializationExpr id) { constructLazyInitializationExpr(id) } or /** * INTERNAL: Do not use. */ @@ -530,8 +530,8 @@ module Synth { /** * INTERNAL: Do not use. */ - TOtherConstructorDeclRefExpr(Raw::OtherConstructorDeclRefExpr id) { - constructOtherConstructorDeclRefExpr(id) + TOtherInitializerRefExpr(Raw::OtherInitializerRefExpr id) { + constructOtherInitializerRefExpr(id) } or /** * INTERNAL: Do not use. @@ -568,8 +568,8 @@ module Synth { /** * INTERNAL: Do not use. */ - TRebindSelfInConstructorExpr(Raw::RebindSelfInConstructorExpr id) { - constructRebindSelfInConstructorExpr(id) + TRebindSelfInInitializerExpr(Raw::RebindSelfInInitializerExpr id) { + constructRebindSelfInInitializerExpr(id) } or /** * INTERNAL: Do not use. @@ -1027,7 +1027,7 @@ module Synth { /** * INTERNAL: Do not use. */ - class TCallable = TAbstractClosureExpr or TAbstractFunctionDecl; + class TCallable = TClosureExpr or TFunction; /** * INTERNAL: Do not use. @@ -1053,11 +1053,6 @@ module Synth { */ class TLocation = TDbLocation or TUnknownLocation; - /** - * INTERNAL: Do not use. - */ - class TAbstractFunctionDecl = TConstructorDecl or TDestructorDecl or TFuncDecl; - /** * INTERNAL: Do not use. */ @@ -1068,6 +1063,11 @@ module Synth { */ class TAbstractTypeParamDecl = TAssociatedTypeDecl or TGenericTypeParamDecl; + /** + * INTERNAL: Do not use. + */ + class TAccessorOrNamedFunction = TAccessor or TNamedFunction; + /** * INTERNAL: Do not use. */ @@ -1079,13 +1079,12 @@ module Synth { /** * INTERNAL: Do not use. */ - class TFuncDecl = TAccessorDecl or TConcreteFuncDecl; + class TFunction = TAccessorOrNamedFunction or TDeinitializer or TInitializer; /** * INTERNAL: Do not use. */ - class TGenericContext = - TAbstractFunctionDecl or TExtensionDecl or TGenericTypeDecl or TSubscriptDecl; + class TGenericContext = TExtensionDecl or TFunction or TGenericTypeDecl or TSubscriptDecl; /** * INTERNAL: Do not use. @@ -1110,18 +1109,13 @@ module Synth { /** * INTERNAL: Do not use. */ - class TValueDecl = TAbstractFunctionDecl or TAbstractStorageDecl or TEnumElementDecl or TTypeDecl; + class TValueDecl = TAbstractStorageDecl or TEnumElementDecl or TFunction or TTypeDecl; /** * INTERNAL: Do not use. */ class TVarDecl = TConcreteVarDecl or TParamDecl; - /** - * INTERNAL: Do not use. - */ - class TAbstractClosureExpr = TAutoClosureExpr or TClosureExpr; - /** * INTERNAL: Do not use. */ @@ -1144,6 +1138,11 @@ module Synth { */ class TCheckedCastExpr = TConditionalCheckedCastExpr or TForcedCheckedCastExpr or TIsExpr; + /** + * INTERNAL: Do not use. + */ + class TClosureExpr = TAutoClosureExpr or TExplicitClosureExpr; + /** * INTERNAL: Do not use. */ @@ -1163,16 +1162,16 @@ module Synth { * INTERNAL: Do not use. */ class TExpr = - TAbstractClosureExpr or TAnyTryExpr or TAppliedPropertyWrapperExpr or TApplyExpr or - TAssignExpr or TBindOptionalExpr or TCaptureListExpr or TCollectionExpr or TDeclRefExpr or + TAnyTryExpr or TAppliedPropertyWrapperExpr or TApplyExpr or TAssignExpr or TBindOptionalExpr or + TCaptureListExpr or TClosureExpr or TCollectionExpr or TDeclRefExpr or TDefaultArgumentExpr or TDiscardAssignmentExpr or TDotSyntaxBaseIgnoredExpr or TDynamicTypeExpr or TEnumIsCaseExpr or TErrorExpr or TExplicitCastExpr or TForceValueExpr or TIdentityExpr or TIfExpr or TImplicitConversionExpr or TInOutExpr or - TKeyPathApplicationExpr or TKeyPathDotExpr or TKeyPathExpr or TLazyInitializerExpr or + TKeyPathApplicationExpr or TKeyPathDotExpr or TKeyPathExpr or TLazyInitializationExpr or TLiteralExpr or TLookupExpr or TMakeTemporarilyEscapableExpr or TObjCSelectorExpr or TOneWayExpr or TOpaqueValueExpr or TOpenExistentialExpr or TOptionalEvaluationExpr or - TOtherConstructorDeclRefExpr or TOverloadedDeclRefExpr or - TPropertyWrapperValuePlaceholderExpr or TRebindSelfInConstructorExpr or TSequenceExpr or + TOtherInitializerRefExpr or TOverloadedDeclRefExpr or + TPropertyWrapperValuePlaceholderExpr or TRebindSelfInInitializerExpr or TSequenceExpr or TSuperRefExpr or TTapExpr or TTupleElementExpr or TTupleExpr or TTypeExpr or TUnresolvedDeclRefExpr or TUnresolvedDotExpr or TUnresolvedMemberExpr or TUnresolvedPatternExpr or TUnresolvedSpecializeExpr or TVarargExpansionExpr; @@ -1220,7 +1219,7 @@ module Synth { /** * INTERNAL: Do not use. */ - class TSelfApplyExpr = TConstructorRefCallExpr or TDotSyntaxCallExpr; + class TSelfApplyExpr = TDotSyntaxCallExpr or TInitializerRefCallExpr; /** * INTERNAL: Do not use. @@ -1419,10 +1418,10 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TAccessorDecl`, if possible. + * Converts a raw element to a synthesized `TAccessor`, if possible. */ cached - TAccessorDecl convertAccessorDeclFromRaw(Raw::Element e) { result = TAccessorDecl(e) } + TAccessor convertAccessorFromRaw(Raw::Element e) { result = TAccessor(e) } /** * INTERNAL: Do not use. @@ -1447,13 +1446,6 @@ module Synth { cached TClassDecl convertClassDeclFromRaw(Raw::Element e) { result = TClassDecl(e) } - /** - * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TConcreteFuncDecl`, if possible. - */ - cached - TConcreteFuncDecl convertConcreteFuncDeclFromRaw(Raw::Element e) { result = TConcreteFuncDecl(e) } - /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TConcreteVarDecl`, if possible. @@ -1463,17 +1455,10 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TConstructorDecl`, if possible. + * Converts a raw element to a synthesized `TDeinitializer`, if possible. */ cached - TConstructorDecl convertConstructorDeclFromRaw(Raw::Element e) { result = TConstructorDecl(e) } - - /** - * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TDestructorDecl`, if possible. - */ - cached - TDestructorDecl convertDestructorDeclFromRaw(Raw::Element e) { result = TDestructorDecl(e) } + TDeinitializer convertDeinitializerFromRaw(Raw::Element e) { result = TDeinitializer(e) } /** * INTERNAL: Do not use. @@ -1535,6 +1520,13 @@ module Synth { result = TInfixOperatorDecl(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TInitializer`, if possible. + */ + cached + TInitializer convertInitializerFromRaw(Raw::Element e) { result = TInitializer(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TMissingMemberDecl`, if possible. @@ -1551,6 +1543,13 @@ module Synth { cached TModuleDecl convertModuleDeclFromRaw(Raw::Element e) { result = TModuleDecl(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TNamedFunction`, if possible. + */ + cached + TNamedFunction convertNamedFunctionFromRaw(Raw::Element e) { result = TNamedFunction(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TOpaqueTypeDecl`, if possible. @@ -1787,13 +1786,6 @@ module Synth { result = TClassMetatypeToObjectExpr(e) } - /** - * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TClosureExpr`, if possible. - */ - cached - TClosureExpr convertClosureExprFromRaw(Raw::Element e) { result = TClosureExpr(e) } - /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TCoerceExpr`, if possible. @@ -1828,15 +1820,6 @@ module Synth { result = TConditionalCheckedCastExpr(e) } - /** - * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TConstructorRefCallExpr`, if possible. - */ - cached - TConstructorRefCallExpr convertConstructorRefCallExprFromRaw(Raw::Element e) { - result = TConstructorRefCallExpr(e) - } - /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TCovariantFunctionConversionExpr`, if possible. @@ -2005,6 +1988,15 @@ module Synth { result = TExistentialMetatypeToObjectExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TExplicitClosureExpr`, if possible. + */ + cached + TExplicitClosureExpr convertExplicitClosureExprFromRaw(Raw::Element e) { + result = TExplicitClosureExpr(e) + } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TFloatLiteralExpr`, if possible. @@ -2076,6 +2068,15 @@ module Synth { result = TInOutToPointerExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TInitializerRefCallExpr`, if possible. + */ + cached + TInitializerRefCallExpr convertInitializerRefCallExprFromRaw(Raw::Element e) { + result = TInitializerRefCallExpr(e) + } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TInjectIntoOptionalExpr`, if possible. @@ -2135,11 +2136,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TLazyInitializerExpr`, if possible. + * Converts a raw element to a synthesized `TLazyInitializationExpr`, if possible. */ cached - TLazyInitializerExpr convertLazyInitializerExprFromRaw(Raw::Element e) { - result = TLazyInitializerExpr(e) + TLazyInitializationExpr convertLazyInitializationExprFromRaw(Raw::Element e) { + result = TLazyInitializationExpr(e) } /** @@ -2283,11 +2284,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TOtherConstructorDeclRefExpr`, if possible. + * Converts a raw element to a synthesized `TOtherInitializerRefExpr`, if possible. */ cached - TOtherConstructorDeclRefExpr convertOtherConstructorDeclRefExprFromRaw(Raw::Element e) { - result = TOtherConstructorDeclRefExpr(e) + TOtherInitializerRefExpr convertOtherInitializerRefExprFromRaw(Raw::Element e) { + result = TOtherInitializerRefExpr(e) } /** @@ -2351,11 +2352,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TRebindSelfInConstructorExpr`, if possible. + * Converts a raw element to a synthesized `TRebindSelfInInitializerExpr`, if possible. */ cached - TRebindSelfInConstructorExpr convertRebindSelfInConstructorExprFromRaw(Raw::Element e) { - result = TRebindSelfInConstructorExpr(e) + TRebindSelfInInitializerExpr convertRebindSelfInInitializerExprFromRaw(Raw::Element e) { + result = TRebindSelfInInitializerExpr(e) } /** @@ -3205,9 +3206,9 @@ module Synth { */ cached TCallable convertCallableFromRaw(Raw::Element e) { - result = convertAbstractClosureExprFromRaw(e) + result = convertClosureExprFromRaw(e) or - result = convertAbstractFunctionDeclFromRaw(e) + result = convertFunctionFromRaw(e) } /** @@ -3299,19 +3300,6 @@ module Synth { result = convertUnknownLocationFromRaw(e) } - /** - * INTERNAL: Do not use. - * Converts a raw DB element to a synthesized `TAbstractFunctionDecl`, if possible. - */ - cached - TAbstractFunctionDecl convertAbstractFunctionDeclFromRaw(Raw::Element e) { - result = convertConstructorDeclFromRaw(e) - or - result = convertDestructorDeclFromRaw(e) - or - result = convertFuncDeclFromRaw(e) - } - /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TAbstractStorageDecl`, if possible. @@ -3334,6 +3322,17 @@ module Synth { result = convertGenericTypeParamDeclFromRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TAccessorOrNamedFunction`, if possible. + */ + cached + TAccessorOrNamedFunction convertAccessorOrNamedFunctionFromRaw(Raw::Element e) { + result = convertAccessorFromRaw(e) + or + result = convertNamedFunctionFromRaw(e) + } + /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TDecl`, if possible. @@ -3367,13 +3366,15 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a raw DB element to a synthesized `TFuncDecl`, if possible. + * Converts a raw DB element to a synthesized `TFunction`, if possible. */ cached - TFuncDecl convertFuncDeclFromRaw(Raw::Element e) { - result = convertAccessorDeclFromRaw(e) + TFunction convertFunctionFromRaw(Raw::Element e) { + result = convertAccessorOrNamedFunctionFromRaw(e) or - result = convertConcreteFuncDeclFromRaw(e) + result = convertDeinitializerFromRaw(e) + or + result = convertInitializerFromRaw(e) } /** @@ -3382,10 +3383,10 @@ module Synth { */ cached TGenericContext convertGenericContextFromRaw(Raw::Element e) { - result = convertAbstractFunctionDeclFromRaw(e) - or result = convertExtensionDeclFromRaw(e) or + result = convertFunctionFromRaw(e) + or result = convertGenericTypeDeclFromRaw(e) or result = convertSubscriptDeclFromRaw(e) @@ -3451,12 +3452,12 @@ module Synth { */ cached TValueDecl convertValueDeclFromRaw(Raw::Element e) { - result = convertAbstractFunctionDeclFromRaw(e) - or result = convertAbstractStorageDeclFromRaw(e) or result = convertEnumElementDeclFromRaw(e) or + result = convertFunctionFromRaw(e) + or result = convertTypeDeclFromRaw(e) } @@ -3471,17 +3472,6 @@ module Synth { result = convertParamDeclFromRaw(e) } - /** - * INTERNAL: Do not use. - * Converts a raw DB element to a synthesized `TAbstractClosureExpr`, if possible. - */ - cached - TAbstractClosureExpr convertAbstractClosureExprFromRaw(Raw::Element e) { - result = convertAutoClosureExprFromRaw(e) - or - result = convertClosureExprFromRaw(e) - } - /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TAnyTryExpr`, if possible. @@ -3540,6 +3530,17 @@ module Synth { result = convertIsExprFromRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TClosureExpr`, if possible. + */ + cached + TClosureExpr convertClosureExprFromRaw(Raw::Element e) { + result = convertAutoClosureExprFromRaw(e) + or + result = convertExplicitClosureExprFromRaw(e) + } + /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TCollectionExpr`, if possible. @@ -3579,8 +3580,6 @@ module Synth { */ cached TExpr convertExprFromRaw(Raw::Element e) { - result = convertAbstractClosureExprFromRaw(e) - or result = convertAnyTryExprFromRaw(e) or result = convertAppliedPropertyWrapperExprFromRaw(e) @@ -3593,6 +3592,8 @@ module Synth { or result = convertCaptureListExprFromRaw(e) or + result = convertClosureExprFromRaw(e) + or result = convertCollectionExprFromRaw(e) or result = convertDeclRefExprFromRaw(e) @@ -3627,7 +3628,7 @@ module Synth { or result = convertKeyPathExprFromRaw(e) or - result = convertLazyInitializerExprFromRaw(e) + result = convertLazyInitializationExprFromRaw(e) or result = convertLiteralExprFromRaw(e) or @@ -3645,13 +3646,13 @@ module Synth { or result = convertOptionalEvaluationExprFromRaw(e) or - result = convertOtherConstructorDeclRefExprFromRaw(e) + result = convertOtherInitializerRefExprFromRaw(e) or result = convertOverloadedDeclRefExprFromRaw(e) or result = convertPropertyWrapperValuePlaceholderExprFromRaw(e) or - result = convertRebindSelfInConstructorExprFromRaw(e) + result = convertRebindSelfInInitializerExprFromRaw(e) or result = convertSequenceExprFromRaw(e) or @@ -3813,9 +3814,9 @@ module Synth { */ cached TSelfApplyExpr convertSelfApplyExprFromRaw(Raw::Element e) { - result = convertConstructorRefCallExprFromRaw(e) - or result = convertDotSyntaxCallExprFromRaw(e) + or + result = convertInitializerRefCallExprFromRaw(e) } /** @@ -4224,10 +4225,10 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TAccessorDecl` to a raw DB element, if possible. + * Converts a synthesized `TAccessor` to a raw DB element, if possible. */ cached - Raw::Element convertAccessorDeclToRaw(TAccessorDecl e) { e = TAccessorDecl(result) } + Raw::Element convertAccessorToRaw(TAccessor e) { e = TAccessor(result) } /** * INTERNAL: Do not use. @@ -4252,13 +4253,6 @@ module Synth { cached Raw::Element convertClassDeclToRaw(TClassDecl e) { e = TClassDecl(result) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TConcreteFuncDecl` to a raw DB element, if possible. - */ - cached - Raw::Element convertConcreteFuncDeclToRaw(TConcreteFuncDecl e) { e = TConcreteFuncDecl(result) } - /** * INTERNAL: Do not use. * Converts a synthesized `TConcreteVarDecl` to a raw DB element, if possible. @@ -4268,17 +4262,10 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TConstructorDecl` to a raw DB element, if possible. + * Converts a synthesized `TDeinitializer` to a raw DB element, if possible. */ cached - Raw::Element convertConstructorDeclToRaw(TConstructorDecl e) { e = TConstructorDecl(result) } - - /** - * INTERNAL: Do not use. - * Converts a synthesized `TDestructorDecl` to a raw DB element, if possible. - */ - cached - Raw::Element convertDestructorDeclToRaw(TDestructorDecl e) { e = TDestructorDecl(result) } + Raw::Element convertDeinitializerToRaw(TDeinitializer e) { e = TDeinitializer(result) } /** * INTERNAL: Do not use. @@ -4340,6 +4327,13 @@ module Synth { e = TInfixOperatorDecl(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TInitializer` to a raw DB element, if possible. + */ + cached + Raw::Element convertInitializerToRaw(TInitializer e) { e = TInitializer(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TMissingMemberDecl` to a raw DB element, if possible. @@ -4356,6 +4350,13 @@ module Synth { cached Raw::Element convertModuleDeclToRaw(TModuleDecl e) { e = TModuleDecl(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TNamedFunction` to a raw DB element, if possible. + */ + cached + Raw::Element convertNamedFunctionToRaw(TNamedFunction e) { e = TNamedFunction(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TOpaqueTypeDecl` to a raw DB element, if possible. @@ -4592,13 +4593,6 @@ module Synth { e = TClassMetatypeToObjectExpr(result) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TClosureExpr` to a raw DB element, if possible. - */ - cached - Raw::Element convertClosureExprToRaw(TClosureExpr e) { e = TClosureExpr(result) } - /** * INTERNAL: Do not use. * Converts a synthesized `TCoerceExpr` to a raw DB element, if possible. @@ -4633,15 +4627,6 @@ module Synth { e = TConditionalCheckedCastExpr(result) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TConstructorRefCallExpr` to a raw DB element, if possible. - */ - cached - Raw::Element convertConstructorRefCallExprToRaw(TConstructorRefCallExpr e) { - e = TConstructorRefCallExpr(result) - } - /** * INTERNAL: Do not use. * Converts a synthesized `TCovariantFunctionConversionExpr` to a raw DB element, if possible. @@ -4810,6 +4795,15 @@ module Synth { e = TExistentialMetatypeToObjectExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TExplicitClosureExpr` to a raw DB element, if possible. + */ + cached + Raw::Element convertExplicitClosureExprToRaw(TExplicitClosureExpr e) { + e = TExplicitClosureExpr(result) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TFloatLiteralExpr` to a raw DB element, if possible. @@ -4881,6 +4875,15 @@ module Synth { e = TInOutToPointerExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TInitializerRefCallExpr` to a raw DB element, if possible. + */ + cached + Raw::Element convertInitializerRefCallExprToRaw(TInitializerRefCallExpr e) { + e = TInitializerRefCallExpr(result) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TInjectIntoOptionalExpr` to a raw DB element, if possible. @@ -4940,11 +4943,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TLazyInitializerExpr` to a raw DB element, if possible. + * Converts a synthesized `TLazyInitializationExpr` to a raw DB element, if possible. */ cached - Raw::Element convertLazyInitializerExprToRaw(TLazyInitializerExpr e) { - e = TLazyInitializerExpr(result) + Raw::Element convertLazyInitializationExprToRaw(TLazyInitializationExpr e) { + e = TLazyInitializationExpr(result) } /** @@ -5086,11 +5089,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TOtherConstructorDeclRefExpr` to a raw DB element, if possible. + * Converts a synthesized `TOtherInitializerRefExpr` to a raw DB element, if possible. */ cached - Raw::Element convertOtherConstructorDeclRefExprToRaw(TOtherConstructorDeclRefExpr e) { - e = TOtherConstructorDeclRefExpr(result) + Raw::Element convertOtherInitializerRefExprToRaw(TOtherInitializerRefExpr e) { + e = TOtherInitializerRefExpr(result) } /** @@ -5154,11 +5157,11 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TRebindSelfInConstructorExpr` to a raw DB element, if possible. + * Converts a synthesized `TRebindSelfInInitializerExpr` to a raw DB element, if possible. */ cached - Raw::Element convertRebindSelfInConstructorExprToRaw(TRebindSelfInConstructorExpr e) { - e = TRebindSelfInConstructorExpr(result) + Raw::Element convertRebindSelfInInitializerExprToRaw(TRebindSelfInInitializerExpr e) { + e = TRebindSelfInInitializerExpr(result) } /** @@ -6008,9 +6011,9 @@ module Synth { */ cached Raw::Element convertCallableToRaw(TCallable e) { - result = convertAbstractClosureExprToRaw(e) + result = convertClosureExprToRaw(e) or - result = convertAbstractFunctionDeclToRaw(e) + result = convertFunctionToRaw(e) } /** @@ -6102,19 +6105,6 @@ module Synth { result = convertUnknownLocationToRaw(e) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TAbstractFunctionDecl` to a raw DB element, if possible. - */ - cached - Raw::Element convertAbstractFunctionDeclToRaw(TAbstractFunctionDecl e) { - result = convertConstructorDeclToRaw(e) - or - result = convertDestructorDeclToRaw(e) - or - result = convertFuncDeclToRaw(e) - } - /** * INTERNAL: Do not use. * Converts a synthesized `TAbstractStorageDecl` to a raw DB element, if possible. @@ -6137,6 +6127,17 @@ module Synth { result = convertGenericTypeParamDeclToRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TAccessorOrNamedFunction` to a raw DB element, if possible. + */ + cached + Raw::Element convertAccessorOrNamedFunctionToRaw(TAccessorOrNamedFunction e) { + result = convertAccessorToRaw(e) + or + result = convertNamedFunctionToRaw(e) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TDecl` to a raw DB element, if possible. @@ -6170,13 +6171,15 @@ module Synth { /** * INTERNAL: Do not use. - * Converts a synthesized `TFuncDecl` to a raw DB element, if possible. + * Converts a synthesized `TFunction` to a raw DB element, if possible. */ cached - Raw::Element convertFuncDeclToRaw(TFuncDecl e) { - result = convertAccessorDeclToRaw(e) + Raw::Element convertFunctionToRaw(TFunction e) { + result = convertAccessorOrNamedFunctionToRaw(e) or - result = convertConcreteFuncDeclToRaw(e) + result = convertDeinitializerToRaw(e) + or + result = convertInitializerToRaw(e) } /** @@ -6185,10 +6188,10 @@ module Synth { */ cached Raw::Element convertGenericContextToRaw(TGenericContext e) { - result = convertAbstractFunctionDeclToRaw(e) - or result = convertExtensionDeclToRaw(e) or + result = convertFunctionToRaw(e) + or result = convertGenericTypeDeclToRaw(e) or result = convertSubscriptDeclToRaw(e) @@ -6254,12 +6257,12 @@ module Synth { */ cached Raw::Element convertValueDeclToRaw(TValueDecl e) { - result = convertAbstractFunctionDeclToRaw(e) - or result = convertAbstractStorageDeclToRaw(e) or result = convertEnumElementDeclToRaw(e) or + result = convertFunctionToRaw(e) + or result = convertTypeDeclToRaw(e) } @@ -6274,17 +6277,6 @@ module Synth { result = convertParamDeclToRaw(e) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TAbstractClosureExpr` to a raw DB element, if possible. - */ - cached - Raw::Element convertAbstractClosureExprToRaw(TAbstractClosureExpr e) { - result = convertAutoClosureExprToRaw(e) - or - result = convertClosureExprToRaw(e) - } - /** * INTERNAL: Do not use. * Converts a synthesized `TAnyTryExpr` to a raw DB element, if possible. @@ -6343,6 +6335,17 @@ module Synth { result = convertIsExprToRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TClosureExpr` to a raw DB element, if possible. + */ + cached + Raw::Element convertClosureExprToRaw(TClosureExpr e) { + result = convertAutoClosureExprToRaw(e) + or + result = convertExplicitClosureExprToRaw(e) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TCollectionExpr` to a raw DB element, if possible. @@ -6382,8 +6385,6 @@ module Synth { */ cached Raw::Element convertExprToRaw(TExpr e) { - result = convertAbstractClosureExprToRaw(e) - or result = convertAnyTryExprToRaw(e) or result = convertAppliedPropertyWrapperExprToRaw(e) @@ -6396,6 +6397,8 @@ module Synth { or result = convertCaptureListExprToRaw(e) or + result = convertClosureExprToRaw(e) + or result = convertCollectionExprToRaw(e) or result = convertDeclRefExprToRaw(e) @@ -6430,7 +6433,7 @@ module Synth { or result = convertKeyPathExprToRaw(e) or - result = convertLazyInitializerExprToRaw(e) + result = convertLazyInitializationExprToRaw(e) or result = convertLiteralExprToRaw(e) or @@ -6448,13 +6451,13 @@ module Synth { or result = convertOptionalEvaluationExprToRaw(e) or - result = convertOtherConstructorDeclRefExprToRaw(e) + result = convertOtherInitializerRefExprToRaw(e) or result = convertOverloadedDeclRefExprToRaw(e) or result = convertPropertyWrapperValuePlaceholderExprToRaw(e) or - result = convertRebindSelfInConstructorExprToRaw(e) + result = convertRebindSelfInInitializerExprToRaw(e) or result = convertSequenceExprToRaw(e) or @@ -6616,9 +6619,9 @@ module Synth { */ cached Raw::Element convertSelfApplyExprToRaw(TSelfApplyExpr e) { - result = convertConstructorRefCallExprToRaw(e) - or result = convertDotSyntaxCallExprToRaw(e) + or + result = convertInitializerRefCallExprToRaw(e) } /** diff --git a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll index 2040fd1f7e5..524d39f20a2 100644 --- a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll +++ b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll @@ -8,14 +8,12 @@ import codeql.swift.elements.KeyPathComponentConstructor import codeql.swift.elements.OtherAvailabilitySpecConstructor import codeql.swift.elements.PlatformVersionAvailabilitySpecConstructor import codeql.swift.elements.UnspecifiedElementConstructor -import codeql.swift.elements.decl.AccessorDeclConstructor +import codeql.swift.elements.decl.AccessorConstructor import codeql.swift.elements.decl.AssociatedTypeDeclConstructor import codeql.swift.elements.decl.CapturedDeclConstructor import codeql.swift.elements.decl.ClassDeclConstructor -import codeql.swift.elements.decl.ConcreteFuncDeclConstructor import codeql.swift.elements.decl.ConcreteVarDeclConstructor -import codeql.swift.elements.decl.ConstructorDeclConstructor -import codeql.swift.elements.decl.DestructorDeclConstructor +import codeql.swift.elements.decl.DeinitializerConstructor import codeql.swift.elements.decl.EnumCaseDeclConstructor import codeql.swift.elements.decl.EnumDeclConstructor import codeql.swift.elements.decl.EnumElementDeclConstructor @@ -24,8 +22,10 @@ import codeql.swift.elements.decl.GenericTypeParamDeclConstructor import codeql.swift.elements.decl.IfConfigDeclConstructor import codeql.swift.elements.decl.ImportDeclConstructor import codeql.swift.elements.decl.InfixOperatorDeclConstructor +import codeql.swift.elements.decl.InitializerConstructor import codeql.swift.elements.decl.MissingMemberDeclConstructor import codeql.swift.elements.decl.ModuleDeclConstructor +import codeql.swift.elements.decl.NamedFunctionConstructor import codeql.swift.elements.decl.OpaqueTypeDeclConstructor import codeql.swift.elements.decl.ParamDeclConstructor import codeql.swift.elements.decl.PatternBindingDeclConstructor @@ -56,12 +56,10 @@ import codeql.swift.elements.expr.BridgeToObjCExprConstructor import codeql.swift.elements.expr.CallExprConstructor import codeql.swift.elements.expr.CaptureListExprConstructor import codeql.swift.elements.expr.ClassMetatypeToObjectExprConstructor -import codeql.swift.elements.expr.ClosureExprConstructor import codeql.swift.elements.expr.CoerceExprConstructor import codeql.swift.elements.expr.CollectionUpcastConversionExprConstructor import codeql.swift.elements.expr.ConditionalBridgeFromObjCExprConstructor import codeql.swift.elements.expr.ConditionalCheckedCastExprConstructor -import codeql.swift.elements.expr.ConstructorRefCallExprConstructor import codeql.swift.elements.expr.CovariantFunctionConversionExprConstructor import codeql.swift.elements.expr.CovariantReturnConversionExprConstructor import codeql.swift.elements.expr.DeclRefExprConstructor @@ -82,6 +80,7 @@ import codeql.swift.elements.expr.EnumIsCaseExprConstructor import codeql.swift.elements.expr.ErasureExprConstructor import codeql.swift.elements.expr.ErrorExprConstructor import codeql.swift.elements.expr.ExistentialMetatypeToObjectExprConstructor +import codeql.swift.elements.expr.ExplicitClosureExprConstructor import codeql.swift.elements.expr.FloatLiteralExprConstructor import codeql.swift.elements.expr.ForceTryExprConstructor import codeql.swift.elements.expr.ForceValueExprConstructor @@ -91,6 +90,7 @@ import codeql.swift.elements.expr.FunctionConversionExprConstructor import codeql.swift.elements.expr.IfExprConstructor import codeql.swift.elements.expr.InOutExprConstructor import codeql.swift.elements.expr.InOutToPointerExprConstructor +import codeql.swift.elements.expr.InitializerRefCallExprConstructor import codeql.swift.elements.expr.InjectIntoOptionalExprConstructor import codeql.swift.elements.expr.IntegerLiteralExprConstructor import codeql.swift.elements.expr.InterpolatedStringLiteralExprConstructor @@ -98,7 +98,7 @@ import codeql.swift.elements.expr.IsExprConstructor import codeql.swift.elements.expr.KeyPathApplicationExprConstructor import codeql.swift.elements.expr.KeyPathDotExprConstructor import codeql.swift.elements.expr.KeyPathExprConstructor -import codeql.swift.elements.expr.LazyInitializerExprConstructor +import codeql.swift.elements.expr.LazyInitializationExprConstructor import codeql.swift.elements.expr.LinearFunctionExprConstructor import codeql.swift.elements.expr.LinearFunctionExtractOriginalExprConstructor import codeql.swift.elements.expr.LinearToDifferentiableFunctionExprConstructor @@ -116,7 +116,7 @@ import codeql.swift.elements.expr.OpaqueValueExprConstructor import codeql.swift.elements.expr.OpenExistentialExprConstructor import codeql.swift.elements.expr.OptionalEvaluationExprConstructor import codeql.swift.elements.expr.OptionalTryExprConstructor -import codeql.swift.elements.expr.OtherConstructorDeclRefExprConstructor +import codeql.swift.elements.expr.OtherInitializerRefExprConstructor import codeql.swift.elements.expr.OverloadedDeclRefExprConstructor import codeql.swift.elements.expr.ParenExprConstructor import codeql.swift.elements.expr.PointerToPointerExprConstructor @@ -124,7 +124,7 @@ import codeql.swift.elements.expr.PostfixUnaryExprConstructor import codeql.swift.elements.expr.PrefixUnaryExprConstructor import codeql.swift.elements.expr.PropertyWrapperValuePlaceholderExprConstructor import codeql.swift.elements.expr.ProtocolMetatypeToObjectExprConstructor -import codeql.swift.elements.expr.RebindSelfInConstructorExprConstructor +import codeql.swift.elements.expr.RebindSelfInInitializerExprConstructor import codeql.swift.elements.expr.RegexLiteralExprConstructor import codeql.swift.elements.expr.SequenceExprConstructor import codeql.swift.elements.expr.StringLiteralExprConstructor diff --git a/swift/ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll index 2e5ad34c6b7..d18b03c2365 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/AbstractStorageDecl.qll @@ -1,39 +1,37 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.AccessorDecl +import codeql.swift.elements.decl.Accessor import codeql.swift.elements.decl.ValueDecl module Generated { class AbstractStorageDecl extends Synth::TAbstractStorageDecl, ValueDecl { /** - * Gets the `index`th accessor declaration of this abstract storage declaration (0-based). + * Gets the `index`th accessor of this abstract storage declaration (0-based). * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - AccessorDecl getImmediateAccessorDecl(int index) { + Accessor getImmediateAccessor(int index) { result = - Synth::convertAccessorDeclFromRaw(Synth::convertAbstractStorageDeclToRaw(this) + Synth::convertAccessorFromRaw(Synth::convertAbstractStorageDeclToRaw(this) .(Raw::AbstractStorageDecl) - .getAccessorDecl(index)) + .getAccessor(index)) } /** - * Gets the `index`th accessor declaration of this abstract storage declaration (0-based). + * Gets the `index`th accessor of this abstract storage declaration (0-based). */ - final AccessorDecl getAccessorDecl(int index) { - result = getImmediateAccessorDecl(index).resolve() - } + final Accessor getAccessor(int index) { result = getImmediateAccessor(index).resolve() } /** - * Gets any of the accessor declarations of this abstract storage declaration. + * Gets any of the accessors of this abstract storage declaration. */ - final AccessorDecl getAnAccessorDecl() { result = getAccessorDecl(_) } + final Accessor getAnAccessor() { result = getAccessor(_) } /** - * Gets the number of accessor declarations of this abstract storage declaration. + * Gets the number of accessors of this abstract storage declaration. */ - final int getNumberOfAccessorDecls() { result = count(int i | exists(getAccessorDecl(i))) } + final int getNumberOfAccessors() { result = count(int i | exists(getAccessor(i))) } } } diff --git a/swift/ql/lib/codeql/swift/generated/decl/AccessorDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/Accessor.qll similarity index 50% rename from swift/ql/lib/codeql/swift/generated/decl/AccessorDecl.qll rename to swift/ql/lib/codeql/swift/generated/decl/Accessor.qll index 6616023d814..b92a158d27d 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/AccessorDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/Accessor.qll @@ -1,54 +1,54 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.FuncDecl +import codeql.swift.elements.decl.AccessorOrNamedFunction module Generated { - class AccessorDecl extends Synth::TAccessorDecl, FuncDecl { - override string getAPrimaryQlClass() { result = "AccessorDecl" } + class Accessor extends Synth::TAccessor, AccessorOrNamedFunction { + override string getAPrimaryQlClass() { result = "Accessor" } /** * Holds if this accessor is a getter. */ - predicate isGetter() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isGetter() } + predicate isGetter() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isGetter() } /** * Holds if this accessor is a setter. */ - predicate isSetter() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isSetter() } + predicate isSetter() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isSetter() } /** * Holds if this accessor is a `willSet`, called before the property is set. */ - predicate isWillSet() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isWillSet() } + predicate isWillSet() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isWillSet() } /** * Holds if this accessor is a `didSet`, called after the property is set. */ - predicate isDidSet() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isDidSet() } + predicate isDidSet() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isDidSet() } /** * Holds if this accessor is a `_read` coroutine, yielding a borrowed value of the property. */ - predicate isRead() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isRead() } + predicate isRead() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isRead() } /** * Holds if this accessor is a `_modify` coroutine, yielding an inout value of the property. */ - predicate isModify() { Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isModify() } + predicate isModify() { Synth::convertAccessorToRaw(this).(Raw::Accessor).isModify() } /** * Holds if this accessor is an `unsafeAddress` immutable addressor. */ predicate isUnsafeAddress() { - Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isUnsafeAddress() + Synth::convertAccessorToRaw(this).(Raw::Accessor).isUnsafeAddress() } /** * Holds if this accessor is an `unsafeMutableAddress` mutable addressor. */ predicate isUnsafeMutableAddress() { - Synth::convertAccessorDeclToRaw(this).(Raw::AccessorDecl).isUnsafeMutableAddress() + Synth::convertAccessorToRaw(this).(Raw::Accessor).isUnsafeMutableAddress() } } } diff --git a/swift/ql/lib/codeql/swift/generated/decl/AccessorOrNamedFunction.qll b/swift/ql/lib/codeql/swift/generated/decl/AccessorOrNamedFunction.qll new file mode 100644 index 00000000000..96ec6448bfa --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/decl/AccessorOrNamedFunction.qll @@ -0,0 +1,11 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.decl.Function + +module Generated { + /** + * INTERNAL: Do not use. + */ + class AccessorOrNamedFunction extends Synth::TAccessorOrNamedFunction, Function { } +} diff --git a/swift/ql/lib/codeql/swift/generated/decl/ConcreteFuncDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/ConcreteFuncDecl.qll deleted file mode 100644 index 8e634daba28..00000000000 --- a/swift/ql/lib/codeql/swift/generated/decl/ConcreteFuncDecl.qll +++ /dev/null @@ -1,10 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.FuncDecl - -module Generated { - class ConcreteFuncDecl extends Synth::TConcreteFuncDecl, FuncDecl { - override string getAPrimaryQlClass() { result = "ConcreteFuncDecl" } - } -} diff --git a/swift/ql/lib/codeql/swift/generated/decl/ConstructorDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/ConstructorDecl.qll deleted file mode 100644 index 8884eb0347e..00000000000 --- a/swift/ql/lib/codeql/swift/generated/decl/ConstructorDecl.qll +++ /dev/null @@ -1,10 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.AbstractFunctionDecl - -module Generated { - class ConstructorDecl extends Synth::TConstructorDecl, AbstractFunctionDecl { - override string getAPrimaryQlClass() { result = "ConstructorDecl" } - } -} diff --git a/swift/ql/lib/codeql/swift/generated/decl/Deinitializer.qll b/swift/ql/lib/codeql/swift/generated/decl/Deinitializer.qll new file mode 100644 index 00000000000..a2adc272df3 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/decl/Deinitializer.qll @@ -0,0 +1,10 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.decl.Function + +module Generated { + class Deinitializer extends Synth::TDeinitializer, Function { + override string getAPrimaryQlClass() { result = "Deinitializer" } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/decl/DestructorDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/DestructorDecl.qll deleted file mode 100644 index bf67c447e5d..00000000000 --- a/swift/ql/lib/codeql/swift/generated/decl/DestructorDecl.qll +++ /dev/null @@ -1,10 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.AbstractFunctionDecl - -module Generated { - class DestructorDecl extends Synth::TDestructorDecl, AbstractFunctionDecl { - override string getAPrimaryQlClass() { result = "DestructorDecl" } - } -} diff --git a/swift/ql/lib/codeql/swift/generated/decl/FuncDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/FuncDecl.qll deleted file mode 100644 index 5d19472ba95..00000000000 --- a/swift/ql/lib/codeql/swift/generated/decl/FuncDecl.qll +++ /dev/null @@ -1,8 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.AbstractFunctionDecl - -module Generated { - class FuncDecl extends Synth::TFuncDecl, AbstractFunctionDecl { } -} diff --git a/swift/ql/lib/codeql/swift/generated/decl/AbstractFunctionDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/Function.qll similarity index 70% rename from swift/ql/lib/codeql/swift/generated/decl/AbstractFunctionDecl.qll rename to swift/ql/lib/codeql/swift/generated/decl/Function.qll index 9320bad86d8..4cc48018fe4 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/AbstractFunctionDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/Function.qll @@ -6,7 +6,5 @@ import codeql.swift.elements.decl.GenericContext import codeql.swift.elements.decl.ValueDecl module Generated { - class AbstractFunctionDecl extends Synth::TAbstractFunctionDecl, GenericContext, ValueDecl, - Callable - { } + class Function extends Synth::TFunction, GenericContext, ValueDecl, Callable { } } diff --git a/swift/ql/lib/codeql/swift/generated/decl/Initializer.qll b/swift/ql/lib/codeql/swift/generated/decl/Initializer.qll new file mode 100644 index 00000000000..01eabb0d295 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/decl/Initializer.qll @@ -0,0 +1,10 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.decl.Function + +module Generated { + class Initializer extends Synth::TInitializer, Function { + override string getAPrimaryQlClass() { result = "Initializer" } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/decl/NamedFunction.qll b/swift/ql/lib/codeql/swift/generated/decl/NamedFunction.qll new file mode 100644 index 00000000000..a2298c86954 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/decl/NamedFunction.qll @@ -0,0 +1,10 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.decl.AccessorOrNamedFunction + +module Generated { + class NamedFunction extends Synth::TNamedFunction, AccessorOrNamedFunction { + override string getAPrimaryQlClass() { result = "NamedFunction" } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/expr/AbstractClosureExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/AbstractClosureExpr.qll deleted file mode 100644 index 1865251d61d..00000000000 --- a/swift/ql/lib/codeql/swift/generated/expr/AbstractClosureExpr.qll +++ /dev/null @@ -1,9 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.Callable -import codeql.swift.elements.expr.Expr - -module Generated { - class AbstractClosureExpr extends Synth::TAbstractClosureExpr, Expr, Callable { } -} diff --git a/swift/ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll index 1eb3018958c..5717c4471db 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/AutoClosureExpr.qll @@ -1,10 +1,10 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.expr.AbstractClosureExpr +import codeql.swift.elements.expr.ClosureExpr module Generated { - class AutoClosureExpr extends Synth::TAutoClosureExpr, AbstractClosureExpr { + class AutoClosureExpr extends Synth::TAutoClosureExpr, ClosureExpr { override string getAPrimaryQlClass() { result = "AutoClosureExpr" } } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll index e971caa1b5b..10bc940dca8 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/CaptureListExpr.qll @@ -1,7 +1,7 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.expr.ClosureExpr +import codeql.swift.elements.expr.ExplicitClosureExpr import codeql.swift.elements.expr.Expr import codeql.swift.elements.decl.PatternBindingDecl @@ -45,9 +45,9 @@ module Generated { * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - ClosureExpr getImmediateClosureBody() { + ExplicitClosureExpr getImmediateClosureBody() { result = - Synth::convertClosureExprFromRaw(Synth::convertCaptureListExprToRaw(this) + Synth::convertExplicitClosureExprFromRaw(Synth::convertCaptureListExprToRaw(this) .(Raw::CaptureListExpr) .getClosureBody()) } @@ -55,6 +55,6 @@ module Generated { /** * Gets the closure body of this capture list expression. */ - final ClosureExpr getClosureBody() { result = getImmediateClosureBody().resolve() } + final ExplicitClosureExpr getClosureBody() { result = getImmediateClosureBody().resolve() } } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/ClosureExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/ClosureExpr.qll index ca6078d07ae..f57343bf94d 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/ClosureExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/ClosureExpr.qll @@ -1,10 +1,9 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.expr.AbstractClosureExpr +import codeql.swift.elements.Callable +import codeql.swift.elements.expr.Expr module Generated { - class ClosureExpr extends Synth::TClosureExpr, AbstractClosureExpr { - override string getAPrimaryQlClass() { result = "ClosureExpr" } - } + class ClosureExpr extends Synth::TClosureExpr, Expr, Callable { } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll index ba2cb92d695..9b4c2c6e46a 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/DotSyntaxCallExpr.qll @@ -4,6 +4,9 @@ private import codeql.swift.generated.Raw import codeql.swift.elements.expr.SelfApplyExpr module Generated { + /** + * INTERNAL: Do not use. + */ class DotSyntaxCallExpr extends Synth::TDotSyntaxCallExpr, SelfApplyExpr { override string getAPrimaryQlClass() { result = "DotSyntaxCallExpr" } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/ExplicitClosureExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/ExplicitClosureExpr.qll new file mode 100644 index 00000000000..b1b3c8782fe --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/expr/ExplicitClosureExpr.qll @@ -0,0 +1,10 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.expr.ClosureExpr + +module Generated { + class ExplicitClosureExpr extends Synth::TExplicitClosureExpr, ClosureExpr { + override string getAPrimaryQlClass() { result = "ExplicitClosureExpr" } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/expr/ConstructorRefCallExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/InitializerRefCallExpr.qll similarity index 58% rename from swift/ql/lib/codeql/swift/generated/expr/ConstructorRefCallExpr.qll rename to swift/ql/lib/codeql/swift/generated/expr/InitializerRefCallExpr.qll index a118877b631..9a0c04618be 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/ConstructorRefCallExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/InitializerRefCallExpr.qll @@ -4,7 +4,10 @@ private import codeql.swift.generated.Raw import codeql.swift.elements.expr.SelfApplyExpr module Generated { - class ConstructorRefCallExpr extends Synth::TConstructorRefCallExpr, SelfApplyExpr { - override string getAPrimaryQlClass() { result = "ConstructorRefCallExpr" } + /** + * INTERNAL: Do not use. + */ + class InitializerRefCallExpr extends Synth::TInitializerRefCallExpr, SelfApplyExpr { + override string getAPrimaryQlClass() { result = "InitializerRefCallExpr" } } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/LazyInitializationExpr.qll similarity index 62% rename from swift/ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll rename to swift/ql/lib/codeql/swift/generated/expr/LazyInitializationExpr.qll index a72d59e9153..0ad1550734e 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/LazyInitializationExpr.qll @@ -4,24 +4,24 @@ private import codeql.swift.generated.Raw import codeql.swift.elements.expr.Expr module Generated { - class LazyInitializerExpr extends Synth::TLazyInitializerExpr, Expr { - override string getAPrimaryQlClass() { result = "LazyInitializerExpr" } + class LazyInitializationExpr extends Synth::TLazyInitializationExpr, Expr { + override string getAPrimaryQlClass() { result = "LazyInitializationExpr" } /** - * Gets the sub expression of this lazy initializer expression. + * Gets the sub expression of this lazy initialization expression. * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ Expr getImmediateSubExpr() { result = - Synth::convertExprFromRaw(Synth::convertLazyInitializerExprToRaw(this) - .(Raw::LazyInitializerExpr) + Synth::convertExprFromRaw(Synth::convertLazyInitializationExprToRaw(this) + .(Raw::LazyInitializationExpr) .getSubExpr()) } /** - * Gets the sub expression of this lazy initializer expression. + * Gets the sub expression of this lazy initialization expression. */ final Expr getSubExpr() { result = getImmediateSubExpr().resolve() } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll index be182390c0f..14e8404cecb 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/ObjCSelectorExpr.qll @@ -1,8 +1,8 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.AbstractFunctionDecl import codeql.swift.elements.expr.Expr +import codeql.swift.elements.decl.Function module Generated { class ObjCSelectorExpr extends Synth::TObjCSelectorExpr, Expr { @@ -32,9 +32,9 @@ module Generated { * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - AbstractFunctionDecl getImmediateMethod() { + Function getImmediateMethod() { result = - Synth::convertAbstractFunctionDeclFromRaw(Synth::convertObjCSelectorExprToRaw(this) + Synth::convertFunctionFromRaw(Synth::convertObjCSelectorExprToRaw(this) .(Raw::ObjCSelectorExpr) .getMethod()) } @@ -42,6 +42,6 @@ module Generated { /** * Gets the method of this obj c selector expression. */ - final AbstractFunctionDecl getMethod() { result = getImmediateMethod().resolve() } + final Function getMethod() { result = getImmediateMethod().resolve() } } } diff --git a/swift/ql/lib/codeql/swift/generated/expr/OtherConstructorDeclRefExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/OtherConstructorDeclRefExpr.qll deleted file mode 100644 index 88daccbcebd..00000000000 --- a/swift/ql/lib/codeql/swift/generated/expr/OtherConstructorDeclRefExpr.qll +++ /dev/null @@ -1,29 +0,0 @@ -// generated by codegen/codegen.py -private import codeql.swift.generated.Synth -private import codeql.swift.generated.Raw -import codeql.swift.elements.decl.ConstructorDecl -import codeql.swift.elements.expr.Expr - -module Generated { - class OtherConstructorDeclRefExpr extends Synth::TOtherConstructorDeclRefExpr, Expr { - override string getAPrimaryQlClass() { result = "OtherConstructorDeclRefExpr" } - - /** - * Gets the constructor declaration of this other constructor declaration reference expression. - * - * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the - * behavior of both the `Immediate` and non-`Immediate` versions. - */ - ConstructorDecl getImmediateConstructorDecl() { - result = - Synth::convertConstructorDeclFromRaw(Synth::convertOtherConstructorDeclRefExprToRaw(this) - .(Raw::OtherConstructorDeclRefExpr) - .getConstructorDecl()) - } - - /** - * Gets the constructor declaration of this other constructor declaration reference expression. - */ - final ConstructorDecl getConstructorDecl() { result = getImmediateConstructorDecl().resolve() } - } -} diff --git a/swift/ql/lib/codeql/swift/generated/expr/OtherInitializerRefExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/OtherInitializerRefExpr.qll new file mode 100644 index 00000000000..605b3a7543d --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/expr/OtherInitializerRefExpr.qll @@ -0,0 +1,29 @@ +// generated by codegen/codegen.py +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.expr.Expr +import codeql.swift.elements.decl.Initializer + +module Generated { + class OtherInitializerRefExpr extends Synth::TOtherInitializerRefExpr, Expr { + override string getAPrimaryQlClass() { result = "OtherInitializerRefExpr" } + + /** + * Gets the initializer of this other initializer reference expression. + * + * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the + * behavior of both the `Immediate` and non-`Immediate` versions. + */ + Initializer getImmediateInitializer() { + result = + Synth::convertInitializerFromRaw(Synth::convertOtherInitializerRefExprToRaw(this) + .(Raw::OtherInitializerRefExpr) + .getInitializer()) + } + + /** + * Gets the initializer of this other initializer reference expression. + */ + final Initializer getInitializer() { result = getImmediateInitializer().resolve() } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/expr/RebindSelfInConstructorExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/RebindSelfInInitializerExpr.qll similarity index 62% rename from swift/ql/lib/codeql/swift/generated/expr/RebindSelfInConstructorExpr.qll rename to swift/ql/lib/codeql/swift/generated/expr/RebindSelfInInitializerExpr.qll index 9be30231208..bc3a934912a 100644 --- a/swift/ql/lib/codeql/swift/generated/expr/RebindSelfInConstructorExpr.qll +++ b/swift/ql/lib/codeql/swift/generated/expr/RebindSelfInInitializerExpr.qll @@ -5,42 +5,42 @@ import codeql.swift.elements.expr.Expr import codeql.swift.elements.decl.VarDecl module Generated { - class RebindSelfInConstructorExpr extends Synth::TRebindSelfInConstructorExpr, Expr { - override string getAPrimaryQlClass() { result = "RebindSelfInConstructorExpr" } + class RebindSelfInInitializerExpr extends Synth::TRebindSelfInInitializerExpr, Expr { + override string getAPrimaryQlClass() { result = "RebindSelfInInitializerExpr" } /** - * Gets the sub expression of this rebind self in constructor expression. + * Gets the sub expression of this rebind self in initializer expression. * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ Expr getImmediateSubExpr() { result = - Synth::convertExprFromRaw(Synth::convertRebindSelfInConstructorExprToRaw(this) - .(Raw::RebindSelfInConstructorExpr) + Synth::convertExprFromRaw(Synth::convertRebindSelfInInitializerExprToRaw(this) + .(Raw::RebindSelfInInitializerExpr) .getSubExpr()) } /** - * Gets the sub expression of this rebind self in constructor expression. + * Gets the sub expression of this rebind self in initializer expression. */ final Expr getSubExpr() { result = getImmediateSubExpr().resolve() } /** - * Gets the self of this rebind self in constructor expression. + * Gets the self of this rebind self in initializer expression. * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ VarDecl getImmediateSelf() { result = - Synth::convertVarDeclFromRaw(Synth::convertRebindSelfInConstructorExprToRaw(this) - .(Raw::RebindSelfInConstructorExpr) + Synth::convertVarDeclFromRaw(Synth::convertRebindSelfInInitializerExprToRaw(this) + .(Raw::RebindSelfInInitializerExpr) .getSelf()) } /** - * Gets the self of this rebind self in constructor expression. + * Gets the self of this rebind self in initializer expression. */ final VarDecl getSelf() { result = getImmediateSelf().resolve() } } diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index f937d9e6309..ba4171b90d0 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -26,8 +26,8 @@ element_is_unknown( ); @callable = - @abstract_closure_expr -| @abstract_function_decl + @closure_expr +| @function ; #keyset[id] @@ -256,8 +256,8 @@ decl_members( //dir=decl ); @generic_context = - @abstract_function_decl -| @extension_decl + @extension_decl +| @function | @generic_type_decl | @subscript_decl ; @@ -391,9 +391,9 @@ top_level_code_decls( //dir=decl ); @value_decl = - @abstract_function_decl -| @abstract_storage_decl + @abstract_storage_decl | @enum_element_decl +| @function | @type_decl ; @@ -403,22 +403,16 @@ value_decls( //dir=decl int interface_type: @type_or_none ref ); -@abstract_function_decl = - @constructor_decl -| @destructor_decl -| @func_decl -; - @abstract_storage_decl = @subscript_decl | @var_decl ; #keyset[id, index] -abstract_storage_decl_accessor_decls( //dir=decl +abstract_storage_decl_accessors( //dir=decl int id: @abstract_storage_decl ref, int index: int ref, - int accessor_decl: @accessor_decl_or_none ref + int accessor: @accessor_or_none ref ); enum_element_decls( //dir=decl @@ -433,6 +427,12 @@ enum_element_decl_params( //dir=decl int param: @param_decl_or_none ref ); +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + infix_operator_decls( //dir=decl unique int id: @infix_operator_decl ); @@ -475,25 +475,25 @@ type_decl_base_types( //dir=decl | @generic_type_param_decl ; -constructor_decls( //dir=decl - unique int id: @constructor_decl -); - -destructor_decls( //dir=decl - unique int id: @destructor_decl -); - -@func_decl = - @accessor_decl -| @concrete_func_decl +@accessor_or_named_function = + @accessor +| @named_function ; +deinitializers( //dir=decl + unique int id: @deinitializer +); + @generic_type_decl = @nominal_type_decl | @opaque_type_decl | @type_alias_decl ; +initializers( //dir=decl + unique int id: @initializer +); + module_decls( //dir=decl unique int id: @module_decl ); @@ -584,58 +584,54 @@ var_decl_property_wrapper_projection_vars( //dir=decl int property_wrapper_projection_var: @var_decl_or_none ref ); -accessor_decls( //dir=decl - unique int id: @accessor_decl +accessors( //dir=decl + unique int id: @accessor ); #keyset[id] -accessor_decl_is_getter( //dir=decl - int id: @accessor_decl ref +accessor_is_getter( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_setter( //dir=decl - int id: @accessor_decl ref +accessor_is_setter( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_will_set( //dir=decl - int id: @accessor_decl ref +accessor_is_will_set( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_did_set( //dir=decl - int id: @accessor_decl ref +accessor_is_did_set( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_read( //dir=decl - int id: @accessor_decl ref +accessor_is_read( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_modify( //dir=decl - int id: @accessor_decl ref +accessor_is_modify( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_unsafe_address( //dir=decl - int id: @accessor_decl ref +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref ); #keyset[id] -accessor_decl_is_unsafe_mutable_address( //dir=decl - int id: @accessor_decl ref +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref ); associated_type_decls( //dir=decl unique int id: @associated_type_decl ); -concrete_func_decls( //dir=decl - unique int id: @concrete_func_decl -); - concrete_var_decls( //dir=decl unique int id: @concrete_var_decl, int introducer_int: int ref @@ -645,6 +641,10 @@ generic_type_param_decls( //dir=decl unique int id: @generic_type_param_decl ); +named_functions( //dir=decl + unique int id: @named_function +); + @nominal_type_decl = @class_decl | @enum_decl @@ -719,13 +719,13 @@ arguments( //dir=expr ); @expr = - @abstract_closure_expr -| @any_try_expr + @any_try_expr | @applied_property_wrapper_expr | @apply_expr | @assign_expr | @bind_optional_expr | @capture_list_expr +| @closure_expr | @collection_expr | @decl_ref_expr | @default_argument_expr @@ -743,7 +743,7 @@ arguments( //dir=expr | @key_path_application_expr | @key_path_dot_expr | @key_path_expr -| @lazy_initializer_expr +| @lazy_initialization_expr | @literal_expr | @lookup_expr | @make_temporarily_escapable_expr @@ -752,10 +752,10 @@ arguments( //dir=expr | @opaque_value_expr | @open_existential_expr | @optional_evaluation_expr -| @other_constructor_decl_ref_expr +| @other_initializer_ref_expr | @overloaded_decl_ref_expr | @property_wrapper_value_placeholder_expr -| @rebind_self_in_constructor_expr +| @rebind_self_in_initializer_expr | @sequence_expr | @super_ref_expr | @tap_expr @@ -776,11 +776,6 @@ expr_types( //dir=expr int type_: @type_or_none ref ); -@abstract_closure_expr = - @auto_closure_expr -| @closure_expr -; - @any_try_expr = @force_try_expr | @optional_try_expr @@ -834,7 +829,7 @@ bind_optional_exprs( //dir=expr capture_list_exprs( //dir=expr unique int id: @capture_list_expr, - int closure_body: @closure_expr_or_none ref + int closure_body: @explicit_closure_expr_or_none ref ); #keyset[id, index] @@ -844,6 +839,11 @@ capture_list_expr_binding_decls( //dir=expr int binding_decl: @pattern_binding_decl_or_none ref ); +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + @collection_expr = @array_expr | @dictionary_expr @@ -1027,8 +1027,8 @@ key_path_expr_components( //dir=expr int component: @key_path_component_or_none ref ); -lazy_initializer_exprs( //dir=expr - unique int id: @lazy_initializer_expr, +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, int sub_expr: @expr_or_none ref ); @@ -1068,7 +1068,7 @@ make_temporarily_escapable_exprs( //dir=expr obj_c_selector_exprs( //dir=expr unique int id: @obj_c_selector_expr, int sub_expr: @expr_or_none ref, - int method: @abstract_function_decl_or_none ref + int method: @function_or_none ref ); one_way_exprs( //dir=expr @@ -1092,9 +1092,9 @@ optional_evaluation_exprs( //dir=expr int sub_expr: @expr_or_none ref ); -other_constructor_decl_ref_exprs( //dir=expr - unique int id: @other_constructor_decl_ref_expr, - int constructor_decl: @constructor_decl_or_none ref +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref ); overloaded_decl_ref_exprs( //dir=expr @@ -1119,8 +1119,8 @@ property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr int wrapped_value: @expr_or_none ref ); -rebind_self_in_constructor_exprs( //dir=expr - unique int id: @rebind_self_in_constructor_expr, +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, int sub_expr: @expr_or_none ref, int self: @var_decl_or_none ref ); @@ -1284,10 +1284,6 @@ class_metatype_to_object_exprs( //dir=expr unique int id: @class_metatype_to_object_expr ); -closure_exprs( //dir=expr - unique int id: @closure_expr -); - coerce_exprs( //dir=expr unique int id: @coerce_expr ); @@ -1352,6 +1348,10 @@ existential_metatype_to_object_exprs( //dir=expr unique int id: @existential_metatype_to_object_expr ); +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + force_try_exprs( //dir=expr unique int id: @force_try_expr ); @@ -1491,8 +1491,8 @@ regex_literal_exprs( //dir=expr ); @self_apply_expr = - @constructor_ref_call_expr -| @dot_syntax_call_expr + @dot_syntax_call_expr +| @initializer_ref_call_expr ; #keyset[id] @@ -1565,10 +1565,6 @@ conditional_checked_cast_exprs( //dir=expr unique int id: @conditional_checked_cast_expr ); -constructor_ref_call_exprs( //dir=expr - unique int id: @constructor_ref_call_expr -); - dot_syntax_call_exprs( //dir=expr unique int id: @dot_syntax_call_expr ); @@ -1585,6 +1581,10 @@ forced_checked_cast_exprs( //dir=expr unique int id: @forced_checked_cast_expr ); +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + is_exprs( //dir=expr unique int id: @is_expr ); @@ -2419,13 +2419,8 @@ variadic_sequence_types( //dir=type unique int id: @variadic_sequence_type ); -@abstract_function_decl_or_none = - @abstract_function_decl -| @unspecified_element -; - -@accessor_decl_or_none = - @accessor_decl +@accessor_or_none = + @accessor | @unspecified_element ; @@ -2474,21 +2469,11 @@ variadic_sequence_types( //dir=type | @unspecified_element ; -@closure_expr_or_none = - @closure_expr -| @unspecified_element -; - @condition_element_or_none = @condition_element | @unspecified_element ; -@constructor_decl_or_none = - @constructor_decl -| @unspecified_element -; - @decl_or_none = @decl | @unspecified_element @@ -2499,6 +2484,11 @@ variadic_sequence_types( //dir=type | @unspecified_element ; +@explicit_closure_expr_or_none = + @explicit_closure_expr +| @unspecified_element +; + @expr_or_none = @expr | @unspecified_element @@ -2509,6 +2499,11 @@ variadic_sequence_types( //dir=type | @unspecified_element ; +@function_or_none = + @function +| @unspecified_element +; + @generic_type_decl_or_none = @generic_type_decl | @unspecified_element @@ -2524,6 +2519,11 @@ variadic_sequence_types( //dir=type | @unspecified_element ; +@initializer_or_none = + @initializer +| @unspecified_element +; + @key_path_component_or_none = @key_path_component | @unspecified_element diff --git a/swift/ql/lib/swift.qll b/swift/ql/lib/swift.qll index 819f14e16eb..608795f8886 100644 --- a/swift/ql/lib/swift.qll +++ b/swift/ql/lib/swift.qll @@ -9,7 +9,7 @@ import codeql.swift.elements.expr.MethodCallExpr import codeql.swift.elements.expr.InitializerCallExpr import codeql.swift.elements.expr.SelfRefExpr import codeql.swift.elements.expr.EnumElementExpr -import codeql.swift.elements.decl.MethodDecl +import codeql.swift.elements.decl.Method import codeql.swift.elements.decl.ClassOrStructDecl import codeql.swift.elements.type.NumericType import codeql.swift.Unit From 82eb0026e6a4c9f1977c033a14371c5d8d08dcb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:53:55 +0200 Subject: [PATCH 33/96] Swift: AST library renamings --- .../ql/lib/codeql/swift/elements/AstNode.qll | 12 +++--- .../codeql/swift/elements/decl/Accessor.qll | 40 +++++++++++++++++++ .../swift/elements/decl/Deinitializer.qll | 9 +++++ .../codeql/swift/elements/decl/Function.qll | 16 ++++++++ .../swift/elements/decl/Initializer.qll | 17 ++++++++ .../decl/{MethodDecl.qll => Method.qll} | 6 +-- .../codeql/swift/elements/expr/ApplyExpr.qll | 4 +- .../codeql/swift/elements/expr/BinaryExpr.qll | 6 +-- .../expr/DotSyntaxBaseIgnoredExpr.qll | 4 +- .../elements/expr/InitializerCallExpr.qll | 4 +- .../elements/expr/InitializerLookupExpr.qll | 6 +-- .../elements/expr/LazyInitializationExpr.qll | 5 +++ .../swift/elements/expr/LogicalOperation.qll | 1 - .../swift/elements/expr/MethodLookupExpr.qll | 8 ++-- .../elements/expr/OtherInitializerRefExpr.qll | 5 +++ .../swift/elements/expr/PostfixUnaryExpr.qll | 4 +- .../swift/elements/expr/PrefixUnaryExpr.qll | 6 +-- .../expr/RebindSelfInInitializerExpr.qll | 5 +++ .../swift/elements/expr/SelfRefExpr.qll | 8 ++-- .../swift/elements/expr/SuperRefExpr.qll | 4 +- .../codeql/swift/printast/PrintAstNode.qll | 6 +-- 21 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 swift/ql/lib/codeql/swift/elements/decl/Accessor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/decl/Deinitializer.qll create mode 100644 swift/ql/lib/codeql/swift/elements/decl/Function.qll create mode 100644 swift/ql/lib/codeql/swift/elements/decl/Initializer.qll rename swift/ql/lib/codeql/swift/elements/decl/{MethodDecl.qll => Method.qll} (94%) create mode 100644 swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExpr.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExpr.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExpr.qll diff --git a/swift/ql/lib/codeql/swift/elements/AstNode.qll b/swift/ql/lib/codeql/swift/elements/AstNode.qll index edbdae81a52..ff45803871d 100644 --- a/swift/ql/lib/codeql/swift/elements/AstNode.qll +++ b/swift/ql/lib/codeql/swift/elements/AstNode.qll @@ -1,7 +1,7 @@ private import codeql.swift.generated.AstNode -private import codeql.swift.elements.decl.AbstractFunctionDecl +private import codeql.swift.elements.decl.Function private import codeql.swift.elements.decl.Decl -private import codeql.swift.elements.expr.AbstractClosureExpr +private import codeql.swift.elements.expr.ClosureExpr private import codeql.swift.elements.Callable private import codeql.swift.generated.ParentChild @@ -15,12 +15,12 @@ private module Cached { Decl getEnclosingDecl(AstNode ast) { result = getEnclosingDeclStep*(getImmediateParent(ast)) } private Element getEnclosingFunctionStep(Element e) { - not e instanceof AbstractFunctionDecl and + not e instanceof Function and result = getEnclosingDecl(e) } cached - AbstractFunctionDecl getEnclosingFunction(AstNode ast) { + Function getEnclosingFunction(AstNode ast) { result = getEnclosingFunctionStep*(getEnclosingDecl(ast)) } @@ -30,7 +30,7 @@ private module Cached { } cached - AbstractClosureExpr getEnclosingClosure(AstNode ast) { + ClosureExpr getEnclosingClosure(AstNode ast) { result = getEnclosingClosureStep*(getImmediateParent(ast)) } } @@ -53,7 +53,7 @@ class AstNode extends Generated::AstNode { * } * ``` */ - final AbstractFunctionDecl getEnclosingFunction() { result = Cached::getEnclosingFunction(this) } + final Function getEnclosingFunction() { result = Cached::getEnclosingFunction(this) } /** * Gets the nearest declaration that contains this AST node, if any. diff --git a/swift/ql/lib/codeql/swift/elements/decl/Accessor.qll b/swift/ql/lib/codeql/swift/elements/decl/Accessor.qll new file mode 100644 index 00000000000..2440ff28d68 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/Accessor.qll @@ -0,0 +1,40 @@ +private import codeql.swift.generated.decl.Accessor + +private predicate isKnownAccessorKind(Accessor decl, string kind) { + decl.isGetter() and kind = "get" + or + decl.isSetter() and kind = "set" + or + decl.isWillSet() and kind = "willSet" + or + decl.isDidSet() and kind = "didSet" + or + decl.isRead() and kind = "_read" + or + decl.isModify() and kind = "_modify" + or + decl.isUnsafeAddress() and kind = "unsafeAddress" + or + decl.isUnsafeMutableAddress() and kind = "unsafeMutableAddress" +} + +class Accessor extends Generated::Accessor { + predicate isPropertyObserver() { + this instanceof WillSetObserver or this instanceof DidSetObserver + } + + override string toString() { + isKnownAccessorKind(this, result) + or + not isKnownAccessorKind(this, _) and + result = super.toString() + } +} + +class WillSetObserver extends Accessor { + WillSetObserver() { this.isWillSet() } +} + +class DidSetObserver extends Accessor { + DidSetObserver() { this.isDidSet() } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/Deinitializer.qll b/swift/ql/lib/codeql/swift/elements/decl/Deinitializer.qll new file mode 100644 index 00000000000..7e16de32d26 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/Deinitializer.qll @@ -0,0 +1,9 @@ +private import codeql.swift.generated.decl.Deinitializer +private import codeql.swift.elements.decl.Method + +/** + * A deinitializer of a class. + */ +class Deinitializer extends Generated::Deinitializer, Method { + override string toString() { result = this.getSelfParam().getType() + "." + super.toString() } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/Function.qll b/swift/ql/lib/codeql/swift/elements/decl/Function.qll new file mode 100644 index 00000000000..ad1fa957d94 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/Function.qll @@ -0,0 +1,16 @@ +private import codeql.swift.generated.decl.Function +private import codeql.swift.elements.decl.Method + +/** + * A function. + */ +class Function extends Generated::Function, Callable { + override string toString() { result = this.getName() } +} + +/** + * A free (non-member) function. + */ +class FreeFunction extends Function { + FreeFunction() { not this instanceof Method } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/Initializer.qll b/swift/ql/lib/codeql/swift/elements/decl/Initializer.qll new file mode 100644 index 00000000000..2b2c903cfcb --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/Initializer.qll @@ -0,0 +1,17 @@ +private import codeql.swift.generated.decl.Initializer +private import codeql.swift.elements.decl.Method +private import codeql.swift.elements.type.FunctionType +private import codeql.swift.elements.type.OptionalType + +/** + * An initializer of a class, struct, enum or protocol. + */ +class Initializer extends Generated::Initializer, Method { + override string toString() { result = this.getSelfParam().getType() + "." + super.toString() } + + /** Holds if this initializer returns an optional type. Failable initializers are written as `init?`. */ + predicate isFailable() { + this.getInterfaceType().(FunctionType).getResult().(FunctionType).getResult() instanceof + OptionalType + } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/Method.qll similarity index 94% rename from swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll rename to swift/ql/lib/codeql/swift/elements/decl/Method.qll index f82a87eb872..6774a7063a8 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/Method.qll @@ -5,15 +5,15 @@ private Decl getAMember(Decl ctx) { or exists(VarDecl var | ctx.getAMember() = var and - var.getAnAccessorDecl() = result + var.getAnAccessor() = result ) } /** * A function that is a member of a class, struct, enum or protocol. */ -class MethodDecl extends AbstractFunctionDecl { - MethodDecl() { +class Method extends Function { + Method() { this = getAMember(any(ClassDecl c)) or this = getAMember(any(StructDecl c)) diff --git a/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll index 67802567b7a..e90937cf15c 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll @@ -4,7 +4,7 @@ private import codeql.swift.elements.expr.DeclRefExpr private import codeql.swift.elements.expr.MethodLookupExpr private import codeql.swift.elements.expr.DotSyntaxBaseIgnoredExpr private import codeql.swift.elements.expr.AutoClosureExpr -private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.decl.Method class ApplyExpr extends Generated::ApplyExpr { Callable getStaticTarget() { result = this.getFunction().(DeclRefExpr).getDecl() } @@ -33,7 +33,7 @@ class MethodApplyExpr extends ApplyExpr { MethodApplyExpr() { method = this.getFunction() } - override MethodDecl getStaticTarget() { result = method.getMethod() } + override Method getStaticTarget() { result = method.getMethod() } override Expr getQualifier() { result = method.getBase() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll index 251f7c889d5..88355ad2d60 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll @@ -1,6 +1,6 @@ private import codeql.swift.generated.expr.BinaryExpr private import codeql.swift.elements.expr.Expr -private import codeql.swift.elements.decl.AbstractFunctionDecl +private import codeql.swift.elements.decl.Function /** * A Swift binary expression, that is, an expression that appears between its @@ -23,7 +23,7 @@ class BinaryExpr extends Generated::BinaryExpr { /** * Gets the operator of this binary expression (the function that is called). */ - AbstractFunctionDecl getOperator() { result = this.getStaticTarget() } + Function getOperator() { result = this.getStaticTarget() } /** * Gets an operand of this binary expression (left or right). @@ -32,5 +32,5 @@ class BinaryExpr extends Generated::BinaryExpr { override string toString() { result = "... " + this.getFunction().toString() + " ..." } - override AbstractFunctionDecl getStaticTarget() { result = super.getStaticTarget() } + override Function getStaticTarget() { result = super.getStaticTarget() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll index e8f35ed5a9d..b6993f9e28f 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll @@ -2,7 +2,7 @@ private import codeql.swift.generated.expr.DotSyntaxBaseIgnoredExpr private import codeql.swift.elements.expr.AutoClosureExpr private import codeql.swift.elements.expr.CallExpr private import codeql.swift.elements.expr.TypeExpr -private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.decl.Method /** * An expression representing a partially applied lookup of an instance property via the receiver's type object. @@ -28,7 +28,7 @@ class DotSyntaxBaseIgnoredExpr extends Generated::DotSyntaxBaseIgnoredExpr { * Gets the underlying instance method that is called when the result of this * expression is fully applied. */ - MethodDecl getMethod() { + Method getMethod() { result = this.getSubExpr() .(AutoClosureExpr) diff --git a/swift/ql/lib/codeql/swift/elements/expr/InitializerCallExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/InitializerCallExpr.qll index 06a3f8c7e4b..dcb4dff4ba9 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/InitializerCallExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/InitializerCallExpr.qll @@ -1,9 +1,9 @@ private import codeql.swift.elements.expr.MethodCallExpr private import codeql.swift.elements.expr.InitializerLookupExpr -private import codeql.swift.elements.decl.ConstructorDecl +private import codeql.swift.elements.decl.Initializer class InitializerCallExpr extends MethodCallExpr { InitializerCallExpr() { this.getFunction() instanceof InitializerLookupExpr } - override ConstructorDecl getStaticTarget() { result = super.getStaticTarget() } + override Initializer getStaticTarget() { result = super.getStaticTarget() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/InitializerLookupExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/InitializerLookupExpr.qll index a853b742fd0..26972894ec6 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/InitializerLookupExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/InitializerLookupExpr.qll @@ -1,10 +1,10 @@ private import codeql.swift.elements.expr.MethodLookupExpr -private import codeql.swift.elements.decl.ConstructorDecl +private import codeql.swift.elements.decl.Initializer class InitializerLookupExpr extends MethodLookupExpr { - InitializerLookupExpr() { super.getMethod() instanceof ConstructorDecl } + InitializerLookupExpr() { super.getMethod() instanceof Initializer } - override ConstructorDecl getMethod() { result = super.getMethod() } + override Initializer getMethod() { result = super.getMethod() } override string toString() { result = this.getMember().toString() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExpr.qll new file mode 100644 index 00000000000..43ecade8779 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializationExpr.qll @@ -0,0 +1,5 @@ +private import codeql.swift.generated.expr.LazyInitializationExpr + +class LazyInitializationExpr extends Generated::LazyInitializationExpr { + override string toString() { result = this.getSubExpr().toString() } +} diff --git a/swift/ql/lib/codeql/swift/elements/expr/LogicalOperation.qll b/swift/ql/lib/codeql/swift/elements/expr/LogicalOperation.qll index 812859a612c..57713551e43 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/LogicalOperation.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/LogicalOperation.qll @@ -3,7 +3,6 @@ private import codeql.swift.elements.expr.BinaryExpr private import codeql.swift.elements.expr.PrefixUnaryExpr private import codeql.swift.elements.expr.DotSyntaxCallExpr private import codeql.swift.elements.expr.DeclRefExpr -private import codeql.swift.elements.decl.ConcreteFuncDecl private predicate unaryHasName(PrefixUnaryExpr e, string name) { e.getStaticTarget().getName() = name diff --git a/swift/ql/lib/codeql/swift/elements/expr/MethodLookupExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/MethodLookupExpr.qll index fa84b9da6fa..4dbdff505b4 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/MethodLookupExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/MethodLookupExpr.qll @@ -1,9 +1,9 @@ private import codeql.swift.generated.expr.MethodLookupExpr private import codeql.swift.elements.expr.MethodLookupExprConstructor private import codeql.swift.elements.expr.DeclRefExpr -private import codeql.swift.elements.expr.OtherConstructorDeclRefExpr +private import codeql.swift.elements.expr.OtherInitializerRefExpr private import codeql.swift.elements.decl.Decl -private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.decl.Method private import codeql.swift.generated.Raw private import codeql.swift.generated.Synth @@ -17,14 +17,14 @@ class MethodLookupExpr extends Generated::MethodLookupExpr { override Decl getImmediateMember() { result = this.getMethodRef().(DeclRefExpr).getDecl() or - result = this.getMethodRef().(OtherConstructorDeclRefExpr).getConstructorDecl() + result = this.getMethodRef().(OtherInitializerRefExpr).getInitializer() } override Expr getImmediateMethodRef() { result = Synth::convertExprFromRaw(this.getUnderlying().getFunction()) } - MethodDecl getMethod() { result = this.getMember() } + Method getMethod() { result = this.getMember() } cached private Raw::SelfApplyExpr getUnderlying() { this = Synth::TMethodLookupExpr(result) } diff --git a/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExpr.qll new file mode 100644 index 00000000000..088dd30f486 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/OtherInitializerRefExpr.qll @@ -0,0 +1,5 @@ +private import codeql.swift.generated.expr.OtherInitializerRefExpr + +class OtherInitializerRefExpr extends Generated::OtherInitializerRefExpr { + override string toString() { result = this.getInitializer().toString() } +} diff --git a/swift/ql/lib/codeql/swift/elements/expr/PostfixUnaryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/PostfixUnaryExpr.qll index 77150da54a1..1358f385fc9 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/PostfixUnaryExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/PostfixUnaryExpr.qll @@ -1,6 +1,6 @@ private import codeql.swift.generated.expr.PostfixUnaryExpr private import codeql.swift.elements.expr.Expr -private import codeql.swift.elements.decl.AbstractFunctionDecl +private import codeql.swift.elements.decl.Function /** * A Swift postfix unary expression, that is, a unary expression that appears @@ -18,5 +18,5 @@ class PostfixUnaryExpr extends Generated::PostfixUnaryExpr { /** * Gets the operator of this postfix unary expression (the function that is called). */ - AbstractFunctionDecl getOperator() { result = this.getStaticTarget() } + Function getOperator() { result = this.getStaticTarget() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/PrefixUnaryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/PrefixUnaryExpr.qll index 8de2b4c7ba1..64b01eb2639 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/PrefixUnaryExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/PrefixUnaryExpr.qll @@ -1,6 +1,6 @@ private import codeql.swift.generated.expr.PrefixUnaryExpr private import codeql.swift.elements.expr.Expr -private import codeql.swift.elements.decl.AbstractFunctionDecl +private import codeql.swift.elements.decl.Function /** * A Swift prefix unary expression, that is, a unary expression that appears @@ -18,7 +18,7 @@ class PrefixUnaryExpr extends Generated::PrefixUnaryExpr { /** * Gets the operator of this prefix unary expression (the function that is called). */ - AbstractFunctionDecl getOperator() { result = this.getStaticTarget() } + Function getOperator() { result = this.getStaticTarget() } - override AbstractFunctionDecl getStaticTarget() { result = super.getStaticTarget() } + override Function getStaticTarget() { result = super.getStaticTarget() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExpr.qll new file mode 100644 index 00000000000..25d20434189 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInInitializerExpr.qll @@ -0,0 +1,5 @@ +private import codeql.swift.generated.expr.RebindSelfInInitializerExpr + +class RebindSelfInInitializerExpr extends Generated::RebindSelfInInitializerExpr { + override string toString() { result = "self = ..." } +} diff --git a/swift/ql/lib/codeql/swift/elements/expr/SelfRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/SelfRefExpr.qll index e412ba33dd1..7ffc7a6af20 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/SelfRefExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/SelfRefExpr.qll @@ -1,14 +1,14 @@ private import codeql.swift.elements.expr.DeclRefExpr -private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.decl.Method private import codeql.swift.elements.decl.VarDecl /** A reference to `self`. */ class SelfRefExpr extends DeclRefExpr { - MethodDecl methodDecl; + Method method; - SelfRefExpr() { this.getDecl() = methodDecl.getSelfParam() } + SelfRefExpr() { this.getDecl() = method.getSelfParam() } VarDecl getSelf() { result = this.getDecl() } - MethodDecl getDeclaringMethod() { result = methodDecl } + Method getDeclaringMethod() { result = method } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll index e731aa253a6..5931f68488b 100644 --- a/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll +++ b/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll @@ -1,9 +1,9 @@ private import codeql.swift.generated.expr.SuperRefExpr -private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.decl.Method /** A reference to `super`. */ class SuperRefExpr extends Generated::SuperRefExpr { override string toString() { result = "super" } - MethodDecl getDeclaringMethod() { this.getSelf() = result.getSelfParam() } + Method getDeclaringMethod() { this.getSelf() = result.getSelfParam() } } diff --git a/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll b/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll index fead27ecf71..57e68648636 100644 --- a/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll +++ b/swift/ql/lib/codeql/swift/printast/PrintAstNode.qll @@ -126,10 +126,10 @@ class PrintVarDecl extends PrintLocatable { } /** - * A specialization of graph node for `AbstractFunctionDecl`, to add typing information. + * A specialization of graph node for `Function`, to add typing information. */ -class PrintAbstractFunctionDecl extends PrintLocatable { - override AbstractFunctionDecl ast; +class PrintFunction extends PrintLocatable { + override Function ast; override string getProperty(string key) { key = "InterfaceType" and result = ast.getInterfaceType().toString() From 4c0384b4f106047da7d08b7f8f76a82ebfb93519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:54:40 +0200 Subject: [PATCH 34/96] Swift: control flow and dataflow library renamings --- .../lib/codeql/swift/controlflow/CfgNodes.qll | 8 +-- .../swift/controlflow/internal/Completion.qll | 2 +- .../internal/ControlFlowElements.qll | 52 +++++++++---------- .../internal/ControlFlowGraphImpl.qll | 42 +++++++-------- .../swift/controlflow/internal/Scope.qll | 2 +- .../codeql/swift/dataflow/ExternalFlow.qll | 12 ++--- swift/ql/lib/codeql/swift/dataflow/Ssa.qll | 2 +- .../dataflow/internal/DataFlowDispatch.qll | 12 ++--- .../dataflow/internal/DataFlowPrivate.qll | 8 +-- .../internal/FlowSummaryImplSpecific.qll | 8 +-- 10 files changed, 74 insertions(+), 74 deletions(-) diff --git a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll index 872fced8a03..b8467b098f2 100644 --- a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll +++ b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll @@ -136,7 +136,7 @@ class PropertyGetterCfgNode extends CfgNode { CfgNode getBase() { result.getAst() = n.getBase() } - AccessorDecl getAccessorDecl() { result = n.getAccessorDecl() } + Accessor getAccessor() { result = n.getAccessor() } } /** A control-flow node that wraps a property setter. */ @@ -149,7 +149,7 @@ class PropertySetterCfgNode extends CfgNode { CfgNode getSource() { result.getAst() = n.getAssignExpr().getSource() } - AccessorDecl getAccessorDecl() { result = n.getAccessorDecl() } + Accessor getAccessor() { result = n.getAccessor() } } class PropertyObserverCfgNode extends CfgNode { @@ -161,7 +161,7 @@ class PropertyObserverCfgNode extends CfgNode { CfgNode getSource() { result.getAst() = n.getAssignExpr().getSource() } - AccessorDecl getAccessorDecl() { result = n.getObserver() } + Accessor getAccessor() { result = n.getObserver() } } class ApplyExprCfgNode extends ExprCfgNode { @@ -171,7 +171,7 @@ class ApplyExprCfgNode extends ExprCfgNode { CfgNode getQualifier() { result.getAst() = e.getQualifier() } - AbstractFunctionDecl getStaticTarget() { result = e.getStaticTarget() } + Callable getStaticTarget() { result = e.getStaticTarget() } Expr getFunction() { result = e.getFunction() } } diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll index aa95602fd97..9e7975890e6 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll @@ -309,7 +309,7 @@ private predicate mayHaveThrowCompletion(ControlFlowElement n) { isThrowingType(n.asAstNode().(ApplyExpr).getFunction().getType()) or // Getters are the only accessor declarators that may throw. - exists(AccessorDecl accessor | isThrowingType(accessor.getInterfaceType()) | + exists(Accessor accessor | isThrowingType(accessor.getInterfaceType()) | isPropertyGetterElement(n, accessor, _) ) } diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll index 8a20ae99b4d..d01f60a1cd1 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll @@ -3,13 +3,13 @@ private import swift cached newtype TControlFlowElement = TAstElement(AstNode n) or - TFuncDeclElement(AbstractFunctionDecl func) { func.hasBody() } or - TClosureElement(ClosureExpr clos) or + TFuncDeclElement(Function func) { func.hasBody() } or + TClosureElement(ExplicitClosureExpr clos) or TPropertyGetterElement(Decl accessor, Expr ref) { isPropertyGetterElement(accessor, ref) } or - TPropertySetterElement(AccessorDecl accessor, AssignExpr assign) { + TPropertySetterElement(Accessor accessor, AssignExpr assign) { isPropertySetterElement(accessor, assign) } or - TPropertyObserverElement(AccessorDecl observer, AssignExpr assign) { + TPropertyObserverElement(Accessor observer, AssignExpr assign) { isPropertyObserverElement(observer, assign) } or TKeyPathElement(KeyPathExpr expr) @@ -24,19 +24,19 @@ predicate ignoreAstElement(AstNode n) { isPropertySetterElement(_, n) } -private AccessorDecl getAnAccessorDecl(Decl d) { - result = d.(VarDecl).getAnAccessorDecl() or - result = d.(SubscriptDecl).getAnAccessorDecl() +private Accessor getAnAccessor(Decl d) { + result = d.(VarDecl).getAnAccessor() or + result = d.(SubscriptDecl).getAnAccessor() } -predicate isPropertyGetterElement(AccessorDecl accessor, Expr ref) { +predicate isPropertyGetterElement(Accessor accessor, Expr ref) { hasDirectToImplementationOrOrdinarySemantics(ref) and isRValue(ref) and accessor.isGetter() and - accessor = getAnAccessorDecl([ref.(LookupExpr).getMember(), ref.(DeclRefExpr).getDecl()]) + accessor = getAnAccessor([ref.(LookupExpr).getMember(), ref.(DeclRefExpr).getDecl()]) } -predicate isPropertyGetterElement(PropertyGetterElement pge, AccessorDecl accessor, Expr ref) { +predicate isPropertyGetterElement(PropertyGetterElement pge, Accessor accessor, Expr ref) { pge = TPropertyGetterElement(accessor, ref) } @@ -60,32 +60,32 @@ private predicate hasDirectToImplementationOrOrdinarySemantics(Expr e) { hasDirectToImplementationSemantics(e) or hasOrdinarySemantics(e) } -private predicate isPropertySetterElement(AccessorDecl accessor, AssignExpr assign) { +private predicate isPropertySetterElement(Accessor accessor, AssignExpr assign) { exists(Expr lhs | lhs = assign.getDest() | hasDirectToImplementationOrOrdinarySemantics(lhs) and accessor.isSetter() and isLValue(lhs) and - accessor = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()]) + accessor = getAnAccessor([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()]) ) } predicate isPropertySetterElement( - PropertySetterElement pse, AccessorDecl accessor, AssignExpr assign + PropertySetterElement pse, Accessor accessor, AssignExpr assign ) { pse = TPropertySetterElement(accessor, assign) } -private predicate isPropertyObserverElement(AccessorDecl observer, AssignExpr assign) { +private predicate isPropertyObserverElement(Accessor observer, AssignExpr assign) { exists(Expr lhs | lhs = assign.getDest() | hasDirectToImplementationOrOrdinarySemantics(lhs) and observer.isPropertyObserver() and isLValue(lhs) and - observer = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()]) + observer = getAnAccessor([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()]) ) } predicate isPropertyObserverElement( - PropertyObserverElement poe, AccessorDecl accessor, AssignExpr assign + PropertyObserverElement poe, Accessor accessor, AssignExpr assign ) { poe = TPropertyObserverElement(accessor, assign) } @@ -111,7 +111,7 @@ class AstElement extends ControlFlowElement, TAstElement { } class PropertyGetterElement extends ControlFlowElement, TPropertyGetterElement { - AccessorDecl accessor; + Accessor accessor; Expr ref; PropertyGetterElement() { this = TPropertyGetterElement(accessor, ref) } @@ -122,13 +122,13 @@ class PropertyGetterElement extends ControlFlowElement, TPropertyGetterElement { Expr getRef() { result = ref } - AccessorDecl getAccessorDecl() { result = accessor } + Accessor getAccessor() { result = accessor } Expr getBase() { result = ref.(LookupExpr).getBase() } } class PropertySetterElement extends ControlFlowElement, TPropertySetterElement { - AccessorDecl accessor; + Accessor accessor; AssignExpr assign; PropertySetterElement() { this = TPropertySetterElement(accessor, assign) } @@ -137,7 +137,7 @@ class PropertySetterElement extends ControlFlowElement, TPropertySetterElement { override Location getLocation() { result = assign.getLocation() } - AccessorDecl getAccessorDecl() { result = accessor } + Accessor getAccessor() { result = accessor } AssignExpr getAssignExpr() { result = assign } @@ -145,7 +145,7 @@ class PropertySetterElement extends ControlFlowElement, TPropertySetterElement { } class PropertyObserverElement extends ControlFlowElement, TPropertyObserverElement { - AccessorDecl observer; + Accessor observer; AssignExpr assign; PropertyObserverElement() { this = TPropertyObserverElement(observer, assign) } @@ -160,7 +160,7 @@ class PropertyObserverElement extends ControlFlowElement, TPropertyObserverEleme override Location getLocation() { result = assign.getLocation() } - AccessorDecl getObserver() { result = observer } + Accessor getObserver() { result = observer } predicate isWillSet() { observer.isWillSet() } @@ -172,7 +172,7 @@ class PropertyObserverElement extends ControlFlowElement, TPropertyObserverEleme } class FuncDeclElement extends ControlFlowElement, TFuncDeclElement { - AbstractFunctionDecl func; + Function func; FuncDeclElement() { this = TFuncDeclElement(func) } @@ -180,7 +180,7 @@ class FuncDeclElement extends ControlFlowElement, TFuncDeclElement { override Location getLocation() { result = func.getLocation() } - AbstractFunctionDecl getAst() { result = func } + Function getAst() { result = func } } class KeyPathElement extends ControlFlowElement, TKeyPathElement { @@ -196,13 +196,13 @@ class KeyPathElement extends ControlFlowElement, TKeyPathElement { } class ClosureElement extends ControlFlowElement, TClosureElement { - ClosureExpr expr; + ExplicitClosureExpr expr; ClosureElement() { this = TClosureElement(expr) } override Location getLocation() { result = expr.getLocation() } - ClosureExpr getAst() { result = expr } + ExplicitClosureExpr getAst() { result = expr } override string toString() { result = expr.toString() } } diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll index 422f98a89c4..d3eb3aaa244 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll @@ -47,7 +47,7 @@ module CfgScope { abstract predicate exit(ControlFlowElement last, Completion c); } - private class BodyStmtCallableScope extends Range_ instanceof AbstractFunctionDecl { + private class BodyStmtCallableScope extends Range_ instanceof Function { Decls::FuncDeclTree tree; BodyStmtCallableScope() { tree.getAst() = this } @@ -67,7 +67,7 @@ module CfgScope { final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) } } - private class ClosureExprScope extends Range_ instanceof ClosureExpr { + private class ClosureExprScope extends Range_ instanceof ExplicitClosureExpr { Exprs::ClosureExprTree tree; ClosureExprScope() { tree.getAst() = this } @@ -1002,17 +1002,17 @@ module Decls { * } * ``` */ - private class AbstractFunctionDeclTree extends AstLeafTree { - override AbstractFunctionDecl ast; + private class FunctionTree extends AstLeafTree { + override Function ast; } /** The control-flow of a function declaration body. */ class FuncDeclTree extends StandardPreOrderTree, TFuncDeclElement { - AbstractFunctionDecl ast; + Function ast; FuncDeclTree() { this = TFuncDeclElement(ast) } - AbstractFunctionDecl getAst() { result = ast } + Function getAst() { result = ast } final override ControlFlowElement getChildElement(int i) { i = -1 and @@ -1107,12 +1107,12 @@ module Exprs { * direct-to-implementation-access semantics. */ class PropertyAssignExpr extends AssignExprTree { - AccessorDecl accessorDecl; + Accessor accessor; - PropertyAssignExpr() { isPropertySetterElement(_, accessorDecl, ast) } + PropertyAssignExpr() { isPropertySetterElement(_, accessor, ast) } final override predicate isLast(ControlFlowElement last, Completion c) { - isPropertySetterElement(last, accessorDecl, ast) and + isPropertySetterElement(last, accessor, ast) and completionIsValidFor(c, last) } @@ -1138,11 +1138,11 @@ module Exprs { } class ClosureExprTree extends StandardPreOrderTree, TClosureElement { - ClosureExpr expr; + ExplicitClosureExpr expr; ClosureExprTree() { this = TClosureElement(expr) } - ClosureExpr getAst() { result = expr } + ExplicitClosureExpr getAst() { result = expr } final override ControlFlowElement getChildElement(int i) { result.asAstNode() = expr.getParam(i) @@ -1175,8 +1175,8 @@ module Exprs { class Closure = @auto_closure_expr or @closure_expr; // TODO: Traverse the expressions in the capture list once we extract it. - private class ClosureTree extends AstLeafTree { - override ClosureExpr ast; + private class ExplicitClosureTree extends AstLeafTree { + override ExplicitClosureExpr ast; } /** @@ -1308,8 +1308,8 @@ module Exprs { } } - private class RebindSelfInConstructorTree extends AstStandardPostOrderTree { - override RebindSelfInConstructorExpr ast; + private class RebindSelfInInitializerTree extends AstStandardPostOrderTree { + override RebindSelfInInitializerExpr ast; final override ControlFlowElement getChildElement(int i) { result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0 @@ -1342,8 +1342,8 @@ module Exprs { } } - private class LazyInitializerTree extends AstStandardPostOrderTree { - override LazyInitializerExpr ast; + private class LazyInitializationTree extends AstStandardPostOrderTree { + override LazyInitializationExpr ast; final override ControlFlowElement getChildElement(int i) { result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0 @@ -1426,8 +1426,8 @@ module Exprs { DeclRefExprLValueTree() { isLValue(ast) } } - class OtherConstructorDeclRefTree extends AstLeafTree { - override OtherConstructorDeclRefExpr ast; + class OtherInitializerRefTree extends AstLeafTree { + override OtherInitializerRefExpr ast; } abstract class DeclRefExprRValueTree extends AstControlFlowTree { @@ -1443,7 +1443,7 @@ module Exprs { } private class PropertyDeclRefRValueTree extends DeclRefExprRValueTree { - AccessorDecl accessor; + Accessor accessor; PropertyDeclRefRValueTree() { isPropertyGetterElement(_, accessor, ast) } @@ -1550,7 +1550,7 @@ module Exprs { * or ordinary semantics that includes a getter. */ private class PropertyMemberRefRValue extends MemberRefRValueTree { - AccessorDecl accessor; + Accessor accessor; PropertyMemberRefRValue() { isPropertyGetterElement(_, accessor, ast) } diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll index b74d001cb6a..43c1adec64c 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll @@ -3,7 +3,7 @@ private import codeql.swift.generated.ParentChild private import codeql.swift.generated.Synth module CallableBase { - class TypeRange = Synth::TAbstractFunctionDecl or Synth::TKeyPathExpr or Synth::TClosureExpr; + class TypeRange = Synth::TFunction or Synth::TKeyPathExpr or Synth::TClosureExpr; class Range extends Scope::Range, TypeRange { } } diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index 672405107d7..eac0cbb1c1a 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -378,7 +378,7 @@ private predicate elementSpec( summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) } -private string paramsStringPart(AbstractFunctionDecl c, int i) { +private string paramsStringPart(Function c, int i) { i = -1 and result = "(" and exists(c) or exists(int n, string p | c.getParam(n).getType().toString() = p | @@ -397,12 +397,12 @@ private string paramsStringPart(AbstractFunctionDecl c, int i) { * Parameter types are represented by their type erasure. */ cached -string paramsString(AbstractFunctionDecl c) { +string paramsString(Function c) { result = concat(int i | | paramsStringPart(c, i) order by i) } bindingset[func] -predicate matchesSignature(AbstractFunctionDecl func, string signature) { +predicate matchesSignature(Function func, string signature) { signature = "" or paramsString(func) = signature } @@ -425,17 +425,17 @@ private Element interpretElement0( namespace = "" and // TODO: Fill out when we properly extract modules. ( // Non-member functions - exists(AbstractFunctionDecl func | + exists(Function func | func.getName() = name and type = "" and matchesSignature(func, signature) and subtypes = false and - not result instanceof MethodDecl and + not result instanceof Method and result = func ) or // Member functions - exists(NominalTypeDecl namedTypeDecl, Decl declWithMethod, MethodDecl method | + exists(NominalTypeDecl namedTypeDecl, Decl declWithMethod, Method method | method.getName() = name and method = declWithMethod.getAMember() and namedTypeDecl.getFullName() = type and diff --git a/swift/ql/lib/codeql/swift/dataflow/Ssa.qll b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll index 44c07c3c5a8..055deaa7009 100644 --- a/swift/ql/lib/codeql/swift/dataflow/Ssa.qll +++ b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll @@ -107,7 +107,7 @@ module Ssa { certain = true ) or - exists(ExitNode exit, AbstractFunctionDecl func | + exists(ExitNode exit, Function func | [func.getAParam(), func.getSelfParam()] = v.asVarDecl() and bb.getNode(i) = exit and modifiableParam(v.asVarDecl()) and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowDispatch.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowDispatch.qll index 6647d176879..5263ec99be2 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowDispatch.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowDispatch.qll @@ -179,7 +179,7 @@ class PropertyGetterCall extends DataFlowCall, TPropertyGetterCall { override Location getLocation() { result = getter.getLocation() } - AccessorDecl getAccessorDecl() { result = getter.getAccessorDecl() } + Accessor getAccessor() { result = getter.getAccessor() } } class PropertySetterCall extends DataFlowCall, TPropertySetterCall { @@ -203,7 +203,7 @@ class PropertySetterCall extends DataFlowCall, TPropertySetterCall { override Location getLocation() { result = setter.getLocation() } - AccessorDecl getAccessorDecl() { result = setter.getAccessorDecl() } + Accessor getAccessor() { result = setter.getAccessor() } } class PropertyObserverCall extends DataFlowCall, TPropertyObserverCall { @@ -230,7 +230,7 @@ class PropertyObserverCall extends DataFlowCall, TPropertyObserverCall { override Location getLocation() { result = observer.getLocation() } - AccessorDecl getAccessorDecl() { result = observer.getAccessorDecl() } + Accessor getAccessor() { result = observer.getAccessor() } } class SummaryCall extends DataFlowCall, TSummaryCall { @@ -261,11 +261,11 @@ private module Cached { DataFlowCallable viableCallable(DataFlowCall call) { result = TDataFlowFunc(call.asCall().getStaticTarget()) or - result = TDataFlowFunc(call.(PropertyGetterCall).getAccessorDecl()) + result = TDataFlowFunc(call.(PropertyGetterCall).getAccessor()) or - result = TDataFlowFunc(call.(PropertySetterCall).getAccessorDecl()) + result = TDataFlowFunc(call.(PropertySetterCall).getAccessor()) or - result = TDataFlowFunc(call.(PropertyObserverCall).getAccessorDecl()) + result = TDataFlowFunc(call.(PropertyObserverCall).getAccessor()) or result = TSummarizedCallable(call.asCall().getStaticTarget()) } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index a11bb602103..3259bc3099e 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -187,7 +187,7 @@ private module Cached { or // flow through nil-coalescing operator `??` exists(BinaryExpr nco | - nco.getOperator().(FreeFunctionDecl).getName() = "??(_:_:)" and + nco.getOperator().(FreeFunction).getName() = "??(_:_:)" and nodeTo.asExpr() = nco | // value argument @@ -487,12 +487,12 @@ private module ReturnNodes { } /** - * A data-flow node that represents the `self` value in a constructor being + * A data-flow node that represents the `self` value in an initializer being * implicitly returned as the newly-constructed object */ class SelfReturnNode extends InoutReturnNodeImpl { SelfReturnNode() { - exit.getScope() instanceof ConstructorDecl and + exit.getScope() instanceof Initializer and param instanceof SelfParamDecl } @@ -688,7 +688,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { ) or // creation of an optional by returning from a failable initializer (`init?`) - exists(ConstructorDecl init | + exists(Initializer init | node1.asExpr().(CallExpr).getStaticTarget() = init and node2 = node1 and // HACK: again, we should ideally have a separate Node case here, and not reuse the CallExpr c instanceof OptionalSomeContentSet and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll index d1e03b14523..f04b2916014 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll @@ -13,7 +13,7 @@ private import codeql.swift.dataflow.ExternalFlow private import codeql.swift.dataflow.FlowSummary as FlowSummary private import codeql.swift.controlflow.CfgNodes -class SummarizedCallableBase = AbstractFunctionDecl; +class SummarizedCallableBase = Function; DataFlowCallable inject(SummarizedCallable c) { result.getUnderlyingCallable() = c } @@ -59,7 +59,7 @@ DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { any( * `input`, output specification `output`, kind `kind`, and provenance `provenance`. */ predicate summaryElement( - AbstractFunctionDecl c, string input, string output, string kind, string provenance + Function c, string input, string output, string kind, string provenance ) { exists( string namespace, string type, boolean subtypes, string name, string signature, string ext @@ -73,7 +73,7 @@ predicate summaryElement( * Holds if a neutral model exists for `c` with provenance `provenance`, * which means that there is no flow through `c`. */ -predicate neutralElement(AbstractFunctionDecl c, string provenance) { none() } +predicate neutralElement(Function c, string provenance) { none() } /** * Holds if an external source specification exists for `e` with output specification @@ -167,7 +167,7 @@ class InterpretNode extends TInterpretNode { DataFlowCallable asCallable() { result.getUnderlyingCallable() = this.asElement() } /** Gets the target of this call, if any. */ - AbstractFunctionDecl getCallTarget() { result = this.asCall().asCall().getStaticTarget() } + Function getCallTarget() { result = this.asCall().asCall().getStaticTarget() } /** Gets a textual representation of this node. */ string toString() { From 3d679703573d20bfc7bc30524c08012e0a0cfadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:56:16 +0200 Subject: [PATCH 35/96] Swift: query library renamings --- swift/ql/lib/codeql/swift/StringFormat.qll | 10 +++++----- swift/ql/lib/codeql/swift/frameworks/AEXML.qll | 6 +++--- .../StandardLibrary/CustomUrlSchemes.qll | 2 +- .../swift/frameworks/StandardLibrary/WebView.qll | 4 ++-- .../CleartextStorageDatabaseExtensions.qll | 2 +- .../CleartextStoragePreferencesExtensions.qll | 4 ++-- .../security/CleartextTransmissionExtensions.qll | 6 +++--- .../swift/security/ConstantPasswordExtensions.qll | 6 +++--- .../swift/security/ConstantSaltExtensions.qll | 4 ++-- .../swift/security/ECBEncryptionExtensions.qll | 2 +- .../codeql/swift/security/ECBEncryptionQuery.qll | 2 +- .../security/HardcodedEncryptionKeyExtensions.qll | 4 ++-- .../InsufficientHashIterationsExtensions.qll | 2 +- .../lib/codeql/swift/security/SensitiveExprs.qll | 10 +++++----- .../swift/security/SqlInjectionExtensions.qll | 14 +++++++------- .../StaticInitializationVectorExtensions.qll | 2 +- .../swift/security/UnsafeJsEvalExtensions.qll | 14 +++++++------- .../security/UnsafeWebViewFetchExtensions.qll | 2 +- .../ql/lib/codeql/swift/security/XXEExtensions.qll | 4 ++-- .../Security/CWE-135/StringLengthConflation.qhelp | 4 ++-- .../Security/CWE-943/PredicateInjection.qhelp | 4 ++-- 21 files changed, 54 insertions(+), 54 deletions(-) diff --git a/swift/ql/lib/codeql/swift/StringFormat.qll b/swift/ql/lib/codeql/swift/StringFormat.qll index 41eeb6efdcd..fc184d7800f 100644 --- a/swift/ql/lib/codeql/swift/StringFormat.qll +++ b/swift/ql/lib/codeql/swift/StringFormat.qll @@ -7,7 +7,7 @@ import swift /** * A function that takes a `printf` style format argument. */ -abstract class FormattingFunction extends AbstractFunctionDecl { +abstract class FormattingFunction extends Function { /** * Gets the position of the format argument. */ @@ -32,7 +32,7 @@ class FormattingFunctionCall extends CallExpr { * An initializer for `String`, `NSString` or `NSMutableString` that takes a * `printf` style format argument. */ -class StringInitWithFormat extends FormattingFunction, MethodDecl { +class StringInitWithFormat extends FormattingFunction, Method { StringInitWithFormat() { exists(string fName | this.hasQualifiedName(["String", "NSString", "NSMutableString"], fName) and @@ -46,7 +46,7 @@ class StringInitWithFormat extends FormattingFunction, MethodDecl { /** * The `localizedStringWithFormat` method of `String`, `NSString` and `NSMutableString`. */ -class LocalizedStringWithFormat extends FormattingFunction, MethodDecl { +class LocalizedStringWithFormat extends FormattingFunction, Method { LocalizedStringWithFormat() { this.hasQualifiedName(["String", "NSString", "NSMutableString"], "localizedStringWithFormat(_:_:)") @@ -58,7 +58,7 @@ class LocalizedStringWithFormat extends FormattingFunction, MethodDecl { /** * The functions `NSLog` and `NSLogv`. */ -class NsLog extends FormattingFunction, FreeFunctionDecl { +class NsLog extends FormattingFunction, FreeFunction { NsLog() { this.getName() = ["NSLog(_:_:)", "NSLogv(_:_:)"] } override int getFormatParameterIndex() { result = 0 } @@ -67,7 +67,7 @@ class NsLog extends FormattingFunction, FreeFunctionDecl { /** * The `NSException.raise` method. */ -class NsExceptionRaise extends FormattingFunction, MethodDecl { +class NsExceptionRaise extends FormattingFunction, Method { NsExceptionRaise() { this.hasQualifiedName("NSException", "raise(_:format:arguments:)") } override int getFormatParameterIndex() { result = 1 } diff --git a/swift/ql/lib/codeql/swift/frameworks/AEXML.qll b/swift/ql/lib/codeql/swift/frameworks/AEXML.qll index da06bfa5d67..a2479286709 100644 --- a/swift/ql/lib/codeql/swift/frameworks/AEXML.qll +++ b/swift/ql/lib/codeql/swift/frameworks/AEXML.qll @@ -7,21 +7,21 @@ import swift /** The creation of an `AEXMLParser`. */ class AexmlParser extends ApplyExpr { AexmlParser() { - this.getStaticTarget().(ConstructorDecl).getEnclosingDecl() instanceof AexmlParserDecl + this.getStaticTarget().(Initializer).getEnclosingDecl() instanceof AexmlParserDecl } } /** The creation of an `AEXMLDocument`. */ class AexmlDocument extends ApplyExpr { AexmlDocument() { - this.getStaticTarget().(ConstructorDecl).getEnclosingDecl() instanceof AexmlDocumentDecl + this.getStaticTarget().(Initializer).getEnclosingDecl() instanceof AexmlDocumentDecl } } /** A call to `AEXMLDocument.loadXML(_:)`. */ class AexmlDocumentLoadXml extends MethodApplyExpr { AexmlDocumentLoadXml() { - exists(MethodDecl f | + exists(Method f | this.getStaticTarget() = f and f.hasName("loadXML(_:)") and f.getEnclosingDecl() instanceof AexmlDocumentDecl diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll index 538e5e18f6c..10460686b4a 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll @@ -51,7 +51,7 @@ private class UrlLaunchOptionsRemoteFlowSource extends RemoteFlowSource { } } -private class ApplicationWithLaunchOptionsFunc extends FuncDecl { +private class ApplicationWithLaunchOptionsFunc extends Function { ApplicationWithLaunchOptionsFunc() { this.getName() = "application(_:" + ["did", "will"] + "FinishLaunchingWithOptions:)" and this.getEnclosingDecl().(ClassOrStructDecl).getABaseTypeDecl*().(ProtocolDecl).getName() = diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll index e40dd35ed5c..0d017309cf9 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/WebView.qll @@ -57,7 +57,7 @@ private class AdoptsWkNavigationDelegate extends Decl { */ private class WKNavigationDelegateSource extends RemoteFlowSource { WKNavigationDelegateSource() { - exists(ParamDecl p, FuncDecl f, AdoptsWkNavigationDelegate t | + exists(ParamDecl p, Function f, AdoptsWkNavigationDelegate t | t.getAMember() = f and f.getName() = [ @@ -170,7 +170,7 @@ private class JsExportedType extends ClassOrStructDecl { */ private class JsExportedSource extends RemoteFlowSource { JsExportedSource() { - exists(MethodDecl adopter, MethodDecl base | + exists(Method adopter, Method base | base.getEnclosingDecl() instanceof JsExportedProto and adopter.getEnclosingDecl() instanceof JsExportedType | diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll index c1e3e62d6f4..51136651eca 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll @@ -38,7 +38,7 @@ private class CoreDataStore extends CleartextStorageDatabaseSink { // values written into Core Data objects through `set*Value` methods are a sink. exists(CallExpr call | call.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("NSManagedObject", ["setValue(_:forKey:)", "setPrimitiveValue(_:forKey:)"]) and call.getArgument(0).getExpr() = this.asExpr() diff --git a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll index 89f97d05809..16ed0266c6a 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll @@ -37,7 +37,7 @@ class CleartextStoragePreferencesAdditionalTaintStep extends Unit { private class UserDefaultsStore extends CleartextStoragePreferencesSink { UserDefaultsStore() { exists(CallExpr call | - call.getStaticTarget().(MethodDecl).hasQualifiedName("UserDefaults", "set(_:forKey:)") and + call.getStaticTarget().(Method).hasQualifiedName("UserDefaults", "set(_:forKey:)") and call.getArgument(0).getExpr() = this.asExpr() ) } @@ -50,7 +50,7 @@ private class NSUbiquitousKeyValueStore extends CleartextStoragePreferencesSink NSUbiquitousKeyValueStore() { exists(CallExpr call | call.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("NSUbiquitousKeyValueStore", "set(_:forKey:)") and call.getArgument(0).getExpr() = this.asExpr() ) diff --git a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll index a7189c7e17a..a39116e4e81 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll @@ -38,7 +38,7 @@ private class NWConnectionSendSink extends CleartextTransmissionSink { // `content` arg to `NWConnection.send` is a sink exists(CallExpr call | call.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("NWConnection", "send(content:contentContext:isComplete:completion:)") and call.getArgument(0).getExpr() = this.asExpr() ) @@ -55,7 +55,7 @@ private class UrlSink extends CleartextTransmissionSink { // (we assume here that the URL goes on to be used in a network operation) exists(CallExpr call | call.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("URL", ["init(string:)", "init(string:relativeTo:)"]) and call.getArgument(0).getExpr() = this.asExpr() ) @@ -70,7 +70,7 @@ private class AlamofireTransmittedSink extends CleartextTransmissionSink { // sinks are the first argument containing the URL, and the `parameters` // and `headers` arguments to appropriate methods of `Session`. exists(CallExpr call, string fName | - call.getStaticTarget().(MethodDecl).hasQualifiedName("Session", fName) and + call.getStaticTarget().(Method).hasQualifiedName("Session", fName) and fName.regexpMatch("(request|streamRequest|download)\\(.*") and ( call.getArgument(0).getExpr() = this.asExpr() or diff --git a/swift/ql/lib/codeql/swift/security/ConstantPasswordExtensions.qll b/swift/ql/lib/codeql/swift/security/ConstantPasswordExtensions.qll index 4324d2226ff..6de5aad120a 100644 --- a/swift/ql/lib/codeql/swift/security/ConstantPasswordExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/ConstantPasswordExtensions.qll @@ -35,7 +35,7 @@ class ConstantPasswordAdditionalTaintStep extends Unit { private class CryptoSwiftPasswordSink extends ConstantPasswordSink { CryptoSwiftPasswordSink() { // `password` arg in `init` is a sink - exists(NominalTypeDecl c, ConstructorDecl f, CallExpr call | + exists(NominalTypeDecl c, Initializer f, CallExpr call | c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and c.getAMember() = f and call.getStaticTarget() = f and @@ -50,7 +50,7 @@ private class CryptoSwiftPasswordSink extends ConstantPasswordSink { private class RnCryptorPasswordSink extends ConstantPasswordSink { RnCryptorPasswordSink() { // RNCryptor (labelled arguments) - exists(NominalTypeDecl c, MethodDecl f, CallExpr call | + exists(NominalTypeDecl c, Method f, CallExpr call | c.getFullName() = [ "RNCryptor", "RNEncryptor", "RNDecryptor", "RNCryptor.EncryptorV3", @@ -63,7 +63,7 @@ private class RnCryptorPasswordSink extends ConstantPasswordSink { ) or // RNCryptor (unlabelled arguments) - exists(MethodDecl f, CallExpr call | + exists(Method f, CallExpr call | f.hasQualifiedName("RNCryptor", "keyForPassword(_:salt:settings:)") and call.getStaticTarget() = f and call.getArgument(0).getExpr() = this.asExpr() diff --git a/swift/ql/lib/codeql/swift/security/ConstantSaltExtensions.qll b/swift/ql/lib/codeql/swift/security/ConstantSaltExtensions.qll index c0a9d6fb33b..ee7d1da9a65 100644 --- a/swift/ql/lib/codeql/swift/security/ConstantSaltExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/ConstantSaltExtensions.qll @@ -35,7 +35,7 @@ class ConstantSaltAdditionalTaintStep extends Unit { private class CryptoSwiftSaltSink extends ConstantSaltSink { CryptoSwiftSaltSink() { // `salt` arg in `init` is a sink - exists(NominalTypeDecl c, ConstructorDecl f, CallExpr call | + exists(NominalTypeDecl c, Initializer f, CallExpr call | c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and c.getAMember() = f and call.getStaticTarget() = f and @@ -49,7 +49,7 @@ private class CryptoSwiftSaltSink extends ConstantSaltSink { */ private class RnCryptorSaltSink extends ConstantSaltSink { RnCryptorSaltSink() { - exists(NominalTypeDecl c, MethodDecl f, CallExpr call | + exists(NominalTypeDecl c, Method f, CallExpr call | c.getFullName() = [ "RNCryptor", "RNEncryptor", "RNDecryptor", "RNCryptor.EncryptorV3", diff --git a/swift/ql/lib/codeql/swift/security/ECBEncryptionExtensions.qll b/swift/ql/lib/codeql/swift/security/ECBEncryptionExtensions.qll index ef59d0459a9..d3b53b1d4f0 100644 --- a/swift/ql/lib/codeql/swift/security/ECBEncryptionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/ECBEncryptionExtensions.qll @@ -43,7 +43,7 @@ class EcbEncryptionAdditionalTaintStep extends Unit { private class CryptoSwiftEcb extends EcbEncryptionSource { CryptoSwiftEcb() { exists(CallExpr call | - call.getStaticTarget().(MethodDecl).hasQualifiedName("ECB", "init()") and + call.getStaticTarget().(Method).hasQualifiedName("ECB", "init()") and this.asExpr() = call ) } diff --git a/swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll b/swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll index fb5900bf16d..c2890b5eb78 100644 --- a/swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll +++ b/swift/ql/lib/codeql/swift/security/ECBEncryptionQuery.qll @@ -9,7 +9,7 @@ import codeql.swift.dataflow.TaintTracking import codeql.swift.security.ECBEncryptionExtensions /** - * A taint configuration from the constructor of ECB mode to expressions that use + * A taint configuration from a creation of an ECB mode instance to expressions that use * it to initialize a cipher. */ module EcbEncryptionConfig implements DataFlow::ConfigSig { diff --git a/swift/ql/lib/codeql/swift/security/HardcodedEncryptionKeyExtensions.qll b/swift/ql/lib/codeql/swift/security/HardcodedEncryptionKeyExtensions.qll index bee8a0db54d..d608fc7b309 100644 --- a/swift/ql/lib/codeql/swift/security/HardcodedEncryptionKeyExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/HardcodedEncryptionKeyExtensions.qll @@ -35,7 +35,7 @@ class HardcodedEncryptionKeyAdditionalTaintStep extends Unit { private class CryptoSwiftEncryptionKeySink extends HardcodedEncryptionKeySink { CryptoSwiftEncryptionKeySink() { // `key` arg in `init` is a sink - exists(NominalTypeDecl c, ConstructorDecl f, CallExpr call | + exists(NominalTypeDecl c, Initializer f, CallExpr call | c.getName() = ["AES", "HMAC", "ChaCha20", "CBCMAC", "CMAC", "Poly1305", "Blowfish", "Rabbit"] and c.getAMember() = f and call.getStaticTarget() = f and @@ -49,7 +49,7 @@ private class CryptoSwiftEncryptionKeySink extends HardcodedEncryptionKeySink { */ private class RnCryptorEncryptionKeySink extends HardcodedEncryptionKeySink { RnCryptorEncryptionKeySink() { - exists(NominalTypeDecl c, MethodDecl f, CallExpr call | + exists(NominalTypeDecl c, Method f, CallExpr call | c.getFullName() = [ "RNCryptor", "RNEncryptor", "RNDecryptor", "RNCryptor.EncryptorV3", diff --git a/swift/ql/lib/codeql/swift/security/InsufficientHashIterationsExtensions.qll b/swift/ql/lib/codeql/swift/security/InsufficientHashIterationsExtensions.qll index 5ecf8d54482..3f7c12465b1 100644 --- a/swift/ql/lib/codeql/swift/security/InsufficientHashIterationsExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/InsufficientHashIterationsExtensions.qll @@ -36,7 +36,7 @@ class InsufficientHashIterationsAdditionalTaintStep extends Unit { private class CryptoSwiftHashIterationsSink extends InsufficientHashIterationsSink { CryptoSwiftHashIterationsSink() { // `iterations` arg in `init` is a sink - exists(NominalTypeDecl c, ConstructorDecl f, CallExpr call | + exists(NominalTypeDecl c, Initializer f, CallExpr call | c.getName() = ["PBKDF1", "PBKDF2"] and c.getAMember() = f and call.getStaticTarget() = f and diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll index 59440c27a51..aa66f6d93fd 100644 --- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll +++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll @@ -86,12 +86,12 @@ private class SensitiveVarDecl extends VarDecl { } /** - * An `AbstractFunctionDecl` that might be used to contain sensitive data. + * A `Function` that might be used to contain sensitive data. */ -private class SensitiveFunctionDecl extends AbstractFunctionDecl { +private class SensitiveFunction extends Function { SensitiveDataType sensitiveType; - SensitiveFunctionDecl() { this.getName().toLowerCase().regexpMatch(sensitiveType.getRegexp()) } + SensitiveFunction() { this.getName().toLowerCase().regexpMatch(sensitiveType.getRegexp()) } predicate hasInfo(string label, SensitiveDataType type) { label = this.getName() and @@ -129,7 +129,7 @@ class SensitiveExpr extends Expr { this.(MemberRefExpr).getMember().(SensitiveVarDecl).hasInfo(label, sensitiveType) or // function call - this.(ApplyExpr).getStaticTarget().(SensitiveFunctionDecl).hasInfo(label, sensitiveType) + this.(ApplyExpr).getStaticTarget().(SensitiveFunction).hasInfo(label, sensitiveType) or // sensitive argument exists(SensitiveArgument a | @@ -155,7 +155,7 @@ class SensitiveExpr extends Expr { /** * A function that is likely used to encrypt or hash data. */ -private class EncryptionFunction extends AbstractFunctionDecl { +private class EncryptionFunction extends Function { EncryptionFunction() { this.getName().regexpMatch(".*(crypt|hash|encode|protect).*") } } diff --git a/swift/ql/lib/codeql/swift/security/SqlInjectionExtensions.qll b/swift/ql/lib/codeql/swift/security/SqlInjectionExtensions.qll index c27cb59feb8..e14afadd593 100644 --- a/swift/ql/lib/codeql/swift/security/SqlInjectionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/SqlInjectionExtensions.qll @@ -33,7 +33,7 @@ private class CApiDefaultSqlInjectionSink extends SqlInjectionSink { // `sqlite3_exec` and variants of `sqlite3_prepare`. exists(CallExpr call | call.getStaticTarget() - .(FreeFunctionDecl) + .(FreeFunction) .hasName([ "sqlite3_exec(_:_:_:_:_:)", "sqlite3_prepare(_:_:_:_:_:)", "sqlite3_prepare_v2(_:_:_:_:_:)", "sqlite3_prepare_v3(_:_:_:_:_:_:)", @@ -53,15 +53,15 @@ private class SQLiteSwiftDefaultSqlInjectionSink extends SqlInjectionSink { // Variants of `Connection.execute`, `connection.prepare` and `connection.scalar`. exists(CallExpr call | call.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("Connection", ["execute(_:)", "prepare(_:_:)", "run(_:_:)", "scalar(_:_:)"]) and call.getArgument(0).getExpr() = this.asExpr() ) or - // String argument to the `Statement` constructor. + // String argument to the `Statement` initializer. exists(CallExpr call | - call.getStaticTarget().(MethodDecl).hasQualifiedName("Statement", "init(_:_:)") and + call.getStaticTarget().(Method).hasQualifiedName("Statement", "init(_:_:)") and call.getArgument(1).getExpr() = this.asExpr() ) } @@ -72,7 +72,7 @@ private class SQLiteSwiftDefaultSqlInjectionSink extends SqlInjectionSink { */ private class GrdbDefaultSqlInjectionSink extends SqlInjectionSink { GrdbDefaultSqlInjectionSink() { - exists(CallExpr call, MethodDecl method | + exists(CallExpr call, Method method | call.getStaticTarget() = method and call.getArgument(0).getExpr() = this.asExpr() | @@ -119,7 +119,7 @@ private class GrdbDefaultSqlInjectionSink extends SqlInjectionSink { method.hasQualifiedName("StatementCache", "statement(_:)") ) or - exists(CallExpr call, MethodDecl method | + exists(CallExpr call, Method method | call.getStaticTarget() = method and call.getArgument(1).getExpr() = this.asExpr() | @@ -133,7 +133,7 @@ private class GrdbDefaultSqlInjectionSink extends SqlInjectionSink { method.hasQualifiedName("SQLStatementCursor", "init(database:sql:arguments:prepFlags:)") ) or - exists(CallExpr call, MethodDecl method | + exists(CallExpr call, Method method | call.getStaticTarget() = method and call.getArgument(3).getExpr() = this.asExpr() | diff --git a/swift/ql/lib/codeql/swift/security/StaticInitializationVectorExtensions.qll b/swift/ql/lib/codeql/swift/security/StaticInitializationVectorExtensions.qll index 65038d430e9..d084946f155 100644 --- a/swift/ql/lib/codeql/swift/security/StaticInitializationVectorExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/StaticInitializationVectorExtensions.qll @@ -51,7 +51,7 @@ private class CryptoSwiftInitializationVectorSink extends StaticInitializationVe */ private class RnCryptorInitializationVectorSink extends StaticInitializationVectorSink { RnCryptorInitializationVectorSink() { - exists(NominalTypeDecl c, MethodDecl f, CallExpr call | + exists(NominalTypeDecl c, Method f, CallExpr call | c.getFullName() = [ "RNCryptor", "RNEncryptor", "RNDecryptor", "RNCryptor.EncryptorV3", diff --git a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll index 39c2e4790f8..32d49253074 100644 --- a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll @@ -32,7 +32,7 @@ private class WKWebViewDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { WKWebViewDefaultUnsafeJsEvalSink() { any(CallExpr ce | ce.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("WKWebView", [ "evaluateJavaScript(_:)", "evaluateJavaScript(_:completionHandler:)", @@ -52,7 +52,7 @@ private class WKUserContentControllerDefaultUnsafeJsEvalSink extends UnsafeJsEva WKUserContentControllerDefaultUnsafeJsEvalSink() { any(CallExpr ce | ce.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("WKUserContentController", "addUserScript(_:)") ).getArgument(0).getExpr() = this.asExpr() } @@ -65,7 +65,7 @@ private class UIWebViewDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { UIWebViewDefaultUnsafeJsEvalSink() { any(CallExpr ce | ce.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName(["UIWebView", "WebView"], "stringByEvaluatingJavaScript(from:)") ).getArgument(0).getExpr() = this.asExpr() } @@ -78,7 +78,7 @@ private class JSContextDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { JSContextDefaultUnsafeJsEvalSink() { any(CallExpr ce | ce.getStaticTarget() - .(MethodDecl) + .(Method) .hasQualifiedName("JSContext", ["evaluateScript(_:)", "evaluateScript(_:withSourceURL:)"]) ).getArgument(0).getExpr() = this.asExpr() } @@ -90,7 +90,7 @@ private class JSContextDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { private class JSEvaluateScriptDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { JSEvaluateScriptDefaultUnsafeJsEvalSink() { any(CallExpr ce | - ce.getStaticTarget().(FreeFunctionDecl).hasName("JSEvaluateScript(_:_:_:_:_:_:)") + ce.getStaticTarget().(FreeFunction).hasName("JSEvaluateScript(_:_:_:_:_:_:)") ).getArgument(1).getExpr() = this.asExpr() } } @@ -104,7 +104,7 @@ private class DefaultUnsafeJsEvalAdditionalTaintStep extends UnsafeJsEvalAdditio arg = any(CallExpr ce | ce.getStaticTarget() - .(FreeFunctionDecl) + .(FreeFunction) .hasName([ "JSStringCreateWithUTF8CString(_:)", "JSStringCreateWithCharacters(_:_:)", "JSStringRetain(_:)" @@ -115,7 +115,7 @@ private class DefaultUnsafeJsEvalAdditionalTaintStep extends UnsafeJsEvalAdditio nodeTo.asExpr() = arg.getApplyExpr() ) or - exists(CallExpr ce, Expr self, AbstractClosureExpr closure | + exists(CallExpr ce, Expr self, ClosureExpr closure | ce.getStaticTarget() .getName() .matches(["withContiguousStorageIfAvailable(%)", "withUnsafeBufferPointer(%)"]) and diff --git a/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll b/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll index 03112d10d54..d0d2cda8864 100644 --- a/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll @@ -39,7 +39,7 @@ private class UIKitWebKitWebViewFetchSink extends UnsafeWebViewFetchSink { UIKitWebKitWebViewFetchSink() { exists( - MethodDecl funcDecl, CallExpr call, string className, string funcName, int arg, int baseArg + Method funcDecl, CallExpr call, string className, string funcName, int arg, int baseArg | // arguments to method calls... ( diff --git a/swift/ql/lib/codeql/swift/security/XXEExtensions.qll b/swift/ql/lib/codeql/swift/security/XXEExtensions.qll index d7debd40cc7..387aadbd1e2 100644 --- a/swift/ql/lib/codeql/swift/security/XXEExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/XXEExtensions.qll @@ -80,7 +80,7 @@ private class XmlDocumentXxeSink extends XxeSink { /** An `XMLDocument` that sets `nodeLoadExternalEntitiesAlways` in its options. */ private class VulnerableXmlDocument extends ApplyExpr { VulnerableXmlDocument() { - this.getStaticTarget().(ConstructorDecl).getEnclosingDecl().(NominalTypeDecl).getFullName() = + this.getStaticTarget().(Initializer).getEnclosingDecl().(NominalTypeDecl).getFullName() = "XMLDocument" and this.getArgument(1).getExpr().(ArrayExpr).getAnElement().(MemberRefExpr).getMember() instanceof NodeLoadExternalEntitiesAlways @@ -192,7 +192,7 @@ private predicate lib2xmlOptionLocalTaintStep(DataFlow::Node source, DataFlow::N exists(ApplyExpr int32Init | int32Init .getStaticTarget() - .(ConstructorDecl) + .(Initializer) .getEnclosingDecl() .(ExtensionDecl) .getExtendedTypeDecl() diff --git a/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.qhelp b/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.qhelp index 15e99e7e407..d0b58d44198 100644 --- a/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.qhelp +++ b/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.qhelp @@ -12,7 +12,7 @@

Use String.count when working with a String. Use NSString.length when working with an NSString. Do not mix values for lengths and offsets between the two types as they are not compatible measures.

-

If you need to convert between Range and NSRange, do so directly using the appropriate constructor. Do not attempt to use incompatible length and offset values to accomplish conversion.

+

If you need to convert between Range and NSRange, do so directly using the appropriate initializer. Do not attempt to use incompatible length and offset values to accomplish conversion.

@@ -33,4 +33,4 @@ - \ No newline at end of file + diff --git a/swift/ql/src/queries/Security/CWE-943/PredicateInjection.qhelp b/swift/ql/src/queries/Security/CWE-943/PredicateInjection.qhelp index 74a87fd4fac..c805e4c2e1f 100644 --- a/swift/ql/src/queries/Security/CWE-943/PredicateInjection.qhelp +++ b/swift/ql/src/queries/Security/CWE-943/PredicateInjection.qhelp @@ -18,11 +18,11 @@ In the following insecure example, NSPredicate is built directly fr

-A better way to do this is to use the arguments parameter of NSPredicate's constructor. This prevents attackers from altering the meaning of the predicate, even if they control the externally obtained data, as seen in the following secure example: +A better way to do this is to use the arguments parameter of NSPredicate's initializer. This prevents attackers from altering the meaning of the predicate, even if they control the externally obtained data, as seen in the following secure example:

  • Apple Developer Documentation: NSPredicate
  • - \ No newline at end of file + From 91a151ec2ae7298d25017b4a1af460ef519af69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 13:57:51 +0200 Subject: [PATCH 36/96] Swift: update tests --- ...ctors.expected => Deinitializers.expected} | 0 .../{Destructors.ql => Deinitializers.ql} | 2 +- .../posix-only/cross-references/Functions.ql | 4 +- ...ructors.expected => Initializers.expected} | 0 .../{Constructors.ql => Initializers.ql} | 2 +- .../posix-only/deduplication/Decls.expected | 4 +- .../posix-only/hello-world/Bodies.ql | 2 +- .../posix-only/linkage-awareness/Bodies.ql | 2 +- swift/ql/test/TestUtils.qll | 4 + .../extractor-tests/expressions/all.expected | 14 +- .../Accessor.expected} | 0 .../AccessorDecl.ql => Accessor/Accessor.ql} | 2 +- .../Accessor_getBody.expected} | 0 .../Accessor_getBody.ql} | 2 +- .../Accessor_getCapture.expected} | 0 .../Accessor_getCapture.ql} | 2 +- .../Accessor_getGenericTypeParam.expected} | 0 .../Accessor_getGenericTypeParam.ql} | 2 +- .../Accessor_getMember.expected} | 0 .../Accessor_getMember.ql} | 2 +- .../Accessor_getName.expected} | 0 .../Accessor_getName.ql} | 2 +- .../Accessor_getParam.expected} | 0 .../Accessor_getParam.ql} | 2 +- .../Accessor_getSelfParam.expected} | 0 .../Accessor_getSelfParam.ql} | 2 +- .../accessors.swift | 0 .../decl/CapturedDecl/PrintAst.expected | 90 +-- .../ConcreteVarDecl/ConcreteVarDecl.expected | 44 +- .../decl/ConcreteVarDecl/ConcreteVarDecl.ql | 10 +- ...d => ConcreteVarDecl_getAccessor.expected} | 0 ...Decl.ql => ConcreteVarDecl_getAccessor.ql} | 2 +- .../MISSING_SOURCE.txt | 0 .../MISSING_SOURCE.txt | 0 .../NamedFunction.expected} | 0 .../NamedFunction.ql} | 2 +- .../NamedFunction_getBody.expected} | 0 .../NamedFunction_getBody.ql} | 2 +- .../NamedFunction_getCapture.expected} | 0 .../NamedFunction_getCapture.ql} | 2 +- ...amedFunction_getGenericTypeParam.expected} | 0 .../NamedFunction_getGenericTypeParam.ql} | 2 +- .../NamedFunction_getMember.expected} | 0 .../NamedFunction_getMember.ql} | 2 +- .../NamedFunction_getName.expected} | 0 .../NamedFunction_getName.ql} | 2 +- .../NamedFunction_getParam.expected} | 0 .../NamedFunction_getParam.ql} | 2 +- .../NamedFunction_getSelfParam.expected} | 0 .../NamedFunction_getSelfParam.ql} | 2 +- .../functions.swift | 0 .../decl/ParamDecl/ParamDecl.expected | 126 ++--- .../generated/decl/ParamDecl/ParamDecl.ql | 10 +- ...xpected => ParamDecl_getAccessor.expected} | 0 ...cessorDecl.ql => ParamDecl_getAccessor.ql} | 2 +- .../MISSING_SOURCE.txt | 0 .../InitializerRefCallExpr.expected} | 0 .../InitializerRefCallExpr.ql} | 2 +- ...itializerRefCallExpr_getArgument.expected} | 0 .../InitializerRefCallExpr_getArgument.ql} | 2 +- .../InitializerRefCallExpr_getType.expected} | 0 .../InitializerRefCallExpr_getType.ql} | 2 +- .../initializer_ref_calls.swift} | 0 .../MISSING_SOURCE.txt | 0 .../MISSING_SOURCE.txt | 0 .../MISSING_SOURCE.txt | 0 .../extractor-tests/types/ThrowingAndAsync.ql | 2 +- .../test/library-tests/ast/PrintAst.expected | 516 +++++++++--------- .../abstractfunctiondecl.expected | 9 - .../elements/decl/function/function.expected | 9 + .../function.ql} | 10 +- .../function.swift} | 0 .../expr/methodlookup/PrintAst.expected | 34 +- 73 files changed, 470 insertions(+), 466 deletions(-) rename swift/integration-tests/posix-only/cross-references/{Destructors.expected => Deinitializers.expected} (100%) rename swift/integration-tests/posix-only/cross-references/{Destructors.ql => Deinitializers.ql} (80%) rename swift/integration-tests/posix-only/cross-references/{Constructors.expected => Initializers.expected} (100%) rename swift/integration-tests/posix-only/cross-references/{Constructors.ql => Initializers.ql} (79%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl.expected => Accessor/Accessor.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl.ql => Accessor/Accessor.ql} (95%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getBody.expected => Accessor/Accessor_getBody.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getBody.ql => Accessor/Accessor_getBody.ql} (87%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getCapture.expected => Accessor/Accessor_getCapture.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getCapture.ql => Accessor/Accessor_getCapture.ql} (83%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getGenericTypeParam.expected => Accessor/Accessor_getGenericTypeParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getGenericTypeParam.ql => Accessor/Accessor_getGenericTypeParam.ql} (84%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getMember.expected => Accessor/Accessor_getMember.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getMember.ql => Accessor/Accessor_getMember.ql} (83%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getName.expected => Accessor/Accessor_getName.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getName.ql => Accessor/Accessor_getName.ql} (87%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getParam.expected => Accessor/Accessor_getParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getParam.ql => Accessor/Accessor_getParam.ql} (83%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getSelfParam.expected => Accessor/Accessor_getSelfParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl/AccessorDecl_getSelfParam.ql => Accessor/Accessor_getSelfParam.ql} (88%) rename swift/ql/test/extractor-tests/generated/decl/{AccessorDecl => Accessor}/accessors.swift (100%) rename swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/{ConcreteVarDecl_getAccessorDecl.expected => ConcreteVarDecl_getAccessor.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/{ConcreteVarDecl_getAccessorDecl.ql => ConcreteVarDecl_getAccessor.ql} (79%) rename swift/ql/test/extractor-tests/generated/decl/{ConstructorDecl => Deinitializer}/MISSING_SOURCE.txt (100%) rename swift/ql/test/extractor-tests/generated/decl/{DestructorDecl => Initializer}/MISSING_SOURCE.txt (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl.expected => NamedFunction/NamedFunction.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl.ql => NamedFunction/NamedFunction.ql} (91%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getBody.expected => NamedFunction/NamedFunction_getBody.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getBody.ql => NamedFunction/NamedFunction_getBody.ql} (85%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getCapture.expected => NamedFunction/NamedFunction_getCapture.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getCapture.ql => NamedFunction/NamedFunction_getCapture.ql} (82%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.expected => NamedFunction/NamedFunction_getGenericTypeParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.ql => NamedFunction/NamedFunction_getGenericTypeParam.ql} (82%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getMember.expected => NamedFunction/NamedFunction_getMember.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getMember.ql => NamedFunction/NamedFunction_getMember.ql} (82%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getName.expected => NamedFunction/NamedFunction_getName.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getName.ql => NamedFunction/NamedFunction_getName.ql} (85%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getParam.expected => NamedFunction/NamedFunction_getParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getParam.ql => NamedFunction/NamedFunction_getParam.ql} (81%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.expected => NamedFunction/NamedFunction_getSelfParam.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.ql => NamedFunction/NamedFunction_getSelfParam.ql} (86%) rename swift/ql/test/extractor-tests/generated/decl/{ConcreteFuncDecl => NamedFunction}/functions.swift (100%) rename swift/ql/test/extractor-tests/generated/decl/ParamDecl/{ParamDecl_getAccessorDecl.expected => ParamDecl_getAccessor.expected} (100%) rename swift/ql/test/extractor-tests/generated/decl/ParamDecl/{ParamDecl_getAccessorDecl.ql => ParamDecl_getAccessor.ql} (78%) rename swift/ql/test/extractor-tests/generated/expr/{ClosureExpr => ExplicitClosureExpr}/MISSING_SOURCE.txt (100%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr.expected => InitializerRefCallExpr/InitializerRefCallExpr.expected} (100%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr.ql => InitializerRefCallExpr/InitializerRefCallExpr.ql} (88%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.expected => InitializerRefCallExpr/InitializerRefCallExpr_getArgument.expected} (100%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql => InitializerRefCallExpr/InitializerRefCallExpr_getArgument.ql} (79%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr_getType.expected => InitializerRefCallExpr/InitializerRefCallExpr_getType.expected} (100%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql => InitializerRefCallExpr/InitializerRefCallExpr_getType.ql} (82%) rename swift/ql/test/extractor-tests/generated/expr/{ConstructorRefCallExpr/constructor_ref_calls.swift => InitializerRefCallExpr/initializer_ref_calls.swift} (100%) rename swift/ql/test/extractor-tests/generated/expr/{LazyInitializerExpr => LazyInitializationExpr}/MISSING_SOURCE.txt (100%) rename swift/ql/test/extractor-tests/generated/expr/{OtherConstructorDeclRefExpr => OtherInitializerRefExpr}/MISSING_SOURCE.txt (100%) rename swift/ql/test/extractor-tests/generated/expr/{RebindSelfInConstructorExpr => RebindSelfInInitializerExpr}/MISSING_SOURCE.txt (100%) delete mode 100644 swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected create mode 100644 swift/ql/test/library-tests/elements/decl/function/function.expected rename swift/ql/test/library-tests/elements/decl/{abstractfunctiondecl/abstractfunctiondecl.ql => function/function.ql} (72%) rename swift/ql/test/library-tests/elements/decl/{abstractfunctiondecl/abstractfunctiondecl.swift => function/function.swift} (100%) diff --git a/swift/integration-tests/posix-only/cross-references/Destructors.expected b/swift/integration-tests/posix-only/cross-references/Deinitializers.expected similarity index 100% rename from swift/integration-tests/posix-only/cross-references/Destructors.expected rename to swift/integration-tests/posix-only/cross-references/Deinitializers.expected diff --git a/swift/integration-tests/posix-only/cross-references/Destructors.ql b/swift/integration-tests/posix-only/cross-references/Deinitializers.ql similarity index 80% rename from swift/integration-tests/posix-only/cross-references/Destructors.ql rename to swift/integration-tests/posix-only/cross-references/Deinitializers.ql index f34b1f9196d..b9291948718 100644 --- a/swift/integration-tests/posix-only/cross-references/Destructors.ql +++ b/swift/integration-tests/posix-only/cross-references/Deinitializers.ql @@ -1,5 +1,5 @@ import swift -from DestructorDecl d +from Deinitializer d where d.getLocation().getFile().getBaseName() != "Package.swift" select d diff --git a/swift/integration-tests/posix-only/cross-references/Functions.ql b/swift/integration-tests/posix-only/cross-references/Functions.ql index 15a91dfead0..c845ec3dd40 100644 --- a/swift/integration-tests/posix-only/cross-references/Functions.ql +++ b/swift/integration-tests/posix-only/cross-references/Functions.ql @@ -1,5 +1,5 @@ -import swift +import codeql.swift.elements.decl.AccessorOrNamedFunction -from FuncDecl f +from AccessorOrNamedFunction f where f.getLocation().getFile().getBaseName() != "Package.swift" select f diff --git a/swift/integration-tests/posix-only/cross-references/Constructors.expected b/swift/integration-tests/posix-only/cross-references/Initializers.expected similarity index 100% rename from swift/integration-tests/posix-only/cross-references/Constructors.expected rename to swift/integration-tests/posix-only/cross-references/Initializers.expected diff --git a/swift/integration-tests/posix-only/cross-references/Constructors.ql b/swift/integration-tests/posix-only/cross-references/Initializers.ql similarity index 79% rename from swift/integration-tests/posix-only/cross-references/Constructors.ql rename to swift/integration-tests/posix-only/cross-references/Initializers.ql index 3fc153f5398..74398846417 100644 --- a/swift/integration-tests/posix-only/cross-references/Constructors.ql +++ b/swift/integration-tests/posix-only/cross-references/Initializers.ql @@ -1,5 +1,5 @@ import swift -from ConstructorDecl d +from Initializer d where d.getLocation().getFile().getBaseName() != "Package.swift" select d diff --git a/swift/integration-tests/posix-only/deduplication/Decls.expected b/swift/integration-tests/posix-only/deduplication/Decls.expected index 829d9e14bc6..5afdb81804a 100644 --- a/swift/integration-tests/posix-only/deduplication/Decls.expected +++ b/swift/integration-tests/posix-only/deduplication/Decls.expected @@ -1,12 +1,12 @@ | Sources/deduplication/def.swift:1:1:1:9 | var ... = ... | PatternBindingDecl | | Sources/deduplication/def.swift:1:5:1:5 | x | ConcreteVarDecl | | Sources/deduplication/def.swift:3:1:3:20 | Generic | StructDecl | -| Sources/deduplication/def.swift:3:8:3:8 | Generic.init() | ConstructorDecl | +| Sources/deduplication/def.swift:3:8:3:8 | Generic.init() | Initializer | | Sources/deduplication/def.swift:3:8:3:8 | self | ParamDecl | | Sources/deduplication/def.swift:3:16:3:16 | T | GenericTypeParamDecl | | Sources/deduplication/def.swift:5:1:5:41 | var ... = ... | PatternBindingDecl | | Sources/deduplication/def.swift:5:5:5:5 | instantiated_generic | ConcreteVarDecl | -| Sources/deduplication/def.swift:7:1:7:42 | function(_:) | ConcreteFuncDecl | +| Sources/deduplication/def.swift:7:1:7:42 | function(_:) | NamedFunction | | Sources/deduplication/def.swift:7:15:7:18 | _ | ParamDecl | | Sources/deduplication/use.swift:1:1:1:13 | var ... = ... | PatternBindingDecl | | Sources/deduplication/use.swift:1:5:1:5 | use_x | ConcreteVarDecl | diff --git a/swift/integration-tests/posix-only/hello-world/Bodies.ql b/swift/integration-tests/posix-only/hello-world/Bodies.ql index 977f1123bc0..591d13248c9 100644 --- a/swift/integration-tests/posix-only/hello-world/Bodies.ql +++ b/swift/integration-tests/posix-only/hello-world/Bodies.ql @@ -1,5 +1,5 @@ import swift -from StructDecl struct, ConstructorDecl decl, BraceStmt body +from StructDecl struct, Initializer decl, BraceStmt body where struct.getName() = "hello_world" and decl = struct.getAMember() and body = decl.getBody() select decl, body diff --git a/swift/integration-tests/posix-only/linkage-awareness/Bodies.ql b/swift/integration-tests/posix-only/linkage-awareness/Bodies.ql index e34c304724e..03bb59ce6b8 100644 --- a/swift/integration-tests/posix-only/linkage-awareness/Bodies.ql +++ b/swift/integration-tests/posix-only/linkage-awareness/Bodies.ql @@ -1,5 +1,5 @@ import swift -from ConcreteFuncDecl decl, BraceStmt body +from NamedFunction decl, BraceStmt body where decl.getName() = "foo()" and decl.getBody() = body select decl, body diff --git a/swift/ql/test/TestUtils.qll b/swift/ql/test/TestUtils.qll index 7cc472fad32..bc8e991b756 100644 --- a/swift/ql/test/TestUtils.qll +++ b/swift/ql/test/TestUtils.qll @@ -1,6 +1,10 @@ private import codeql.swift.elements private import codeql.swift.generated.ParentChild +// Internal classes are not imported by the tests: +import codeql.swift.elements.expr.InitializerRefCallExpr +import codeql.swift.elements.expr.DotSyntaxCallExpr + cached predicate toBeTested(Element e) { e instanceof File diff --git a/swift/ql/test/extractor-tests/expressions/all.expected b/swift/ql/test/extractor-tests/expressions/all.expected index 43812382416..0434e5f7005 100644 --- a/swift/ql/test/extractor-tests/expressions/all.expected +++ b/swift/ql/test/extractor-tests/expressions/all.expected @@ -86,7 +86,7 @@ | expressions.swift:38:14:38:14 | 7 | IntegerLiteralExpr | | expressions.swift:41:1:41:1 | closured(closure:) | DeclRefExpr | | expressions.swift:41:1:43:1 | call to closured(closure:) | CallExpr | -| expressions.swift:41:10:43:1 | { ... } | ClosureExpr | +| expressions.swift:41:10:43:1 | { ... } | ExplicitClosureExpr | | expressions.swift:42:12:42:12 | x | DeclRefExpr | | expressions.swift:42:12:42:16 | ... .+(_:_:) ... | BinaryExpr | | expressions.swift:42:14:42:14 | +(_:_:) | DeclRefExpr | @@ -95,7 +95,7 @@ | expressions.swift:42:16:42:16 | y | DeclRefExpr | | expressions.swift:44:1:44:1 | closured(closure:) | DeclRefExpr | | expressions.swift:44:1:46:1 | call to closured(closure:) | CallExpr | -| expressions.swift:44:10:46:1 | { ... } | ClosureExpr | +| expressions.swift:44:10:46:1 | { ... } | ExplicitClosureExpr | | expressions.swift:45:12:45:12 | x | DeclRefExpr | | expressions.swift:45:12:45:16 | ... .+(_:_:) ... | BinaryExpr | | expressions.swift:45:14:45:14 | +(_:_:) | DeclRefExpr | @@ -104,7 +104,7 @@ | expressions.swift:45:16:45:16 | y | DeclRefExpr | | expressions.swift:47:1:47:1 | closured(closure:) | DeclRefExpr | | expressions.swift:47:1:47:27 | call to closured(closure:) | CallExpr | -| expressions.swift:47:10:47:27 | { ... } | ClosureExpr | +| expressions.swift:47:10:47:27 | { ... } | ExplicitClosureExpr | | expressions.swift:47:19:47:19 | $0 | DeclRefExpr | | expressions.swift:47:19:47:24 | ... .+(_:_:) ... | BinaryExpr | | expressions.swift:47:22:47:22 | +(_:_:) | DeclRefExpr | @@ -113,7 +113,7 @@ | expressions.swift:47:24:47:24 | $1 | DeclRefExpr | | expressions.swift:48:1:48:1 | closured(closure:) | DeclRefExpr | | expressions.swift:48:1:48:20 | call to closured(closure:) | CallExpr | -| expressions.swift:48:10:48:20 | { ... } | ClosureExpr | +| expressions.swift:48:10:48:20 | { ... } | ExplicitClosureExpr | | expressions.swift:48:12:48:12 | $0 | DeclRefExpr | | expressions.swift:48:12:48:17 | ... .+(_:_:) ... | BinaryExpr | | expressions.swift:48:15:48:15 | +(_:_:) | DeclRefExpr | @@ -134,7 +134,7 @@ | expressions.swift:60:23:60:23 | (Int) ... | LoadExpr | | expressions.swift:60:23:60:23 | myNumber | DeclRefExpr | | expressions.swift:60:33:60:63 | ((UnsafePointer) throws -> ()) ... | FunctionConversionExpr | -| expressions.swift:60:33:60:63 | { ... } | ClosureExpr | +| expressions.swift:60:33:60:63 | { ... } | ExplicitClosureExpr | | expressions.swift:60:35:60:35 | unsafeFunction(pointer:) | DeclRefExpr | | expressions.swift:60:35:60:61 | call to unsafeFunction(pointer:) | CallExpr | | expressions.swift:60:59:60:59 | $0 | DeclRefExpr | @@ -158,8 +158,8 @@ | expressions.swift:79:5:79:5 | super | SuperRefExpr | | expressions.swift:79:5:79:11 | Base.init(x:) | MethodLookupExpr | | expressions.swift:79:5:79:21 | call to Base.init(x:) | CallExpr | -| expressions.swift:79:5:79:21 | self = ... | RebindSelfInConstructorExpr | -| expressions.swift:79:11:79:11 | Base.init(x:) | OtherConstructorDeclRefExpr | +| expressions.swift:79:5:79:21 | self = ... | RebindSelfInInitializerExpr | +| expressions.swift:79:11:79:11 | Base.init(x:) | OtherInitializerRefExpr | | expressions.swift:79:19:79:19 | 22 | IntegerLiteralExpr | | expressions.swift:83:15:83:15 | Derived.Type | TypeExpr | | expressions.swift:83:15:83:15 | Derived.init() | DeclRefExpr | diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor.ql similarity index 95% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor.ql index 6dd85dc8bb9..15141f16eb1 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor.ql @@ -3,7 +3,7 @@ import codeql.swift.elements import TestUtils from - AccessorDecl x, string hasName, string hasSelfParam, int getNumberOfParams, string hasBody, + Accessor x, string hasName, string hasSelfParam, int getNumberOfParams, string hasBody, int getNumberOfCaptures, int getNumberOfGenericTypeParams, ModuleDecl getModule, int getNumberOfMembers, Type getInterfaceType, string isGetter, string isSetter, string isWillSet, string isDidSet, string isRead, string isModify, string isUnsafeAddress, diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.ql similarity index 87% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.ql index e83079fc990..34a7fbc86a4 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getBody.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x +from Accessor x where toBeTested(x) and not x.isUnknown() select x, x.getBody() diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.ql similarity index 83% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.ql index f16158c9230..d35a6a3af8f 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getCapture.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x, int index +from Accessor x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getCapture(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.ql similarity index 84% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.ql index 54b9c1a27fd..1075d722ea4 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getGenericTypeParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getGenericTypeParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x, int index +from Accessor x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getGenericTypeParam(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.ql similarity index 83% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.ql index c712c7589f8..74c1741c8c1 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getMember.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getMember.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x, int index +from Accessor x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getMember(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.ql similarity index 87% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.ql index c4ba8be5a03..db49afbc42c 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getName.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getName.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x +from Accessor x where toBeTested(x) and not x.isUnknown() select x, x.getName() diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.ql similarity index 83% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.ql index de48b6dd6ca..ea2d077f5e6 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x, int index +from Accessor x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getParam(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.expected b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.expected rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.ql b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.ql similarity index 88% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.ql rename to swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.ql index 06b4ccbf2fe..44f37b59454 100644 --- a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getSelfParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/Accessor/Accessor_getSelfParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from AccessorDecl x +from Accessor x where toBeTested(x) and not x.isUnknown() select x, x.getSelfParam() diff --git a/swift/ql/test/extractor-tests/generated/decl/AccessorDecl/accessors.swift b/swift/ql/test/extractor-tests/generated/decl/Accessor/accessors.swift similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/AccessorDecl/accessors.swift rename to swift/ql/test/extractor-tests/generated/decl/Accessor/accessors.swift diff --git a/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected b/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected index 601aa9212e3..d7746863677 100644 --- a/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected +++ b/swift/ql/test/extractor-tests/generated/decl/CapturedDecl/PrintAst.expected @@ -1,10 +1,10 @@ closures.swift: -# 1| [ConcreteFuncDecl] hello() +# 1| [NamedFunction] hello() # 1| InterfaceType = () -> String # 1| getBody(): [BraceStmt] { ... } # 2| getElement(0): [ReturnStmt] return ... # 2| getResult(): [StringLiteralExpr] Hello world! -# 5| [ConcreteFuncDecl] captureList() +# 5| [NamedFunction] captureList() # 5| InterfaceType = () -> () # 5| getBody(): [BraceStmt] { ... } # 6| getElement(0): [PatternBindingDecl] var ... = ... @@ -18,7 +18,7 @@ closures.swift: # 7| getInit(0): [CallExpr] call to hello() # 7| getFunction(): [DeclRefExpr] hello() # 7| getPattern(0): [NamedPattern] x -# 7| getClosureBody(): [ClosureExpr] { ... } +# 7| getClosureBody(): [ExplicitClosureExpr] { ... } # 7| getBody(): [BraceStmt] { ... } # 8| getElement(0): [CallExpr] call to print(_:separator:terminator:) # 8| getFunction(): [DeclRefExpr] print(_:separator:terminator:) @@ -55,7 +55,7 @@ closures.swift: # 12| getTypeRepr(): [TypeRepr] (() -> ())? # 12| [ConcreteVarDecl] escape # 12| Type = (() -> ())? -# 14| [ConcreteFuncDecl] setEscape() +# 14| [NamedFunction] setEscape() # 14| InterfaceType = () -> () # 14| getBody(): [BraceStmt] { ... } # 15| getElement(0): [PatternBindingDecl] var ... = ... @@ -65,7 +65,7 @@ closures.swift: # 15| Type = Int # 16| getElement(2): [AssignExpr] ... = ... # 16| getDest(): [DeclRefExpr] escape -# 16| getSource(): [ClosureExpr] { ... } +# 16| getSource(): [ExplicitClosureExpr] { ... } # 16| getBody(): [BraceStmt] { ... } # 17| getElement(0): [BinaryExpr] ... .+=(_:_:) ... # 17| getFunction(): [MethodLookupExpr] .+=(_:_:) @@ -92,7 +92,7 @@ closures.swift: # 17| getCapture(0): [CapturedDecl] x # 16| getSource().getFullyConverted(): [InjectIntoOptionalExpr] ((() -> ())?) ... # 16| getCapture(0): [CapturedDecl] escape -# 22| [ConcreteFuncDecl] callEscape() +# 22| [NamedFunction] callEscape() # 22| InterfaceType = () -> () # 22| getBody(): [BraceStmt] { ... } # 23| getElement(0): [CallExpr] call to setEscape() @@ -104,11 +104,11 @@ closures.swift: # 24| getFunction().getFullyConverted(): [LoadExpr] ((() -> ())) ... # 24| getSubExpr().getFullyConverted(): [InjectIntoOptionalExpr] (()?) ... # 24| getCapture(0): [CapturedDecl] escape -# 27| [ConcreteFuncDecl] logical() +# 27| [NamedFunction] logical() # 27| InterfaceType = () -> Bool # 27| getBody(): [BraceStmt] { ... } # 28| getElement(0): [PatternBindingDecl] var ... = ... -# 28| getInit(0): [ClosureExpr] { ... } +# 28| getInit(0): [ExplicitClosureExpr] { ... } # 28| getParam(0): [ParamDecl] x # 28| Type = Int # 28| getBody(): [BraceStmt] { ... } @@ -194,15 +194,15 @@ closures.swift: # 31| getResult().getFullyConverted(): [ParenExpr] (...) # 31| getCapture(0): [CapturedDecl] x # 32| getCapture(1): [CapturedDecl] f -# 35| [ConcreteFuncDecl] asyncTest() +# 35| [NamedFunction] asyncTest() # 35| InterfaceType = () -> () # 35| getBody(): [BraceStmt] { ... } -# 36| getElement(0): [ConcreteFuncDecl] withCallback(_:) +# 36| getElement(0): [NamedFunction] withCallback(_:) # 36| InterfaceType = (@escaping (Int) async -> Int) -> () # 36| getParam(0): [ParamDecl] callback # 36| Type = (Int) async -> Int # 36| getBody(): [BraceStmt] { ... } -# 38| getElement(0): [ConcreteFuncDecl] wrapper(_:) +# 38| getElement(0): [NamedFunction] wrapper(_:) # 38| InterfaceType = @Sendable (Int) async -> Int # 38| getParam(0): [ParamDecl] x # 38| Type = Int @@ -230,7 +230,7 @@ closures.swift: # 41| getArgument(0): [Argument] priority: default priority # 41| getExpr(): [DefaultArgumentExpr] default priority # 41| getArgument(1): [Argument] operation: { ... } -# 41| getExpr(): [ClosureExpr] { ... } +# 41| getExpr(): [ExplicitClosureExpr] { ... } # 41| getBody(): [BraceStmt] { ... } # 42| getElement(0): [ReturnStmt] return ... # 42| getResult(): [CallExpr] call to print(_:separator:terminator:) @@ -254,7 +254,7 @@ closures.swift: # 45| getElement(1): [CallExpr] call to withCallback(_:) # 45| getFunction(): [DeclRefExpr] withCallback(_:) # 45| getArgument(0): [Argument] : { ... } -# 45| getExpr(): [ClosureExpr] { ... } +# 45| getExpr(): [ExplicitClosureExpr] { ... } # 45| getParam(0): [ParamDecl] x # 45| Type = Int # 45| getBody(): [BraceStmt] { ... } @@ -269,7 +269,7 @@ closures.swift: # 46| getArgument(1): [Argument] : 1 # 46| getExpr(): [IntegerLiteralExpr] 1 # 41| [NilLiteralExpr] nil -# 50| [ConcreteFuncDecl] foo() +# 50| [NamedFunction] foo() # 50| InterfaceType = () -> Int # 50| getBody(): [BraceStmt] { ... } # 51| getElement(0): [PatternBindingDecl] var ... = ... @@ -278,7 +278,7 @@ closures.swift: # 51| getElement(1): [ConcreteVarDecl] x # 51| Type = Int # 52| getElement(2): [PatternBindingDecl] var ... = ... -# 52| getInit(0): [ClosureExpr] { ... } +# 52| getInit(0): [ExplicitClosureExpr] { ... } # 52| getParam(0): [ParamDecl] y # 52| Type = Int # 52| getBody(): [BraceStmt] { ... } @@ -308,7 +308,7 @@ closures.swift: # 53| getArgument(1): [Argument] : 40 # 53| getExpr(): [IntegerLiteralExpr] 40 # 54| getElement(5): [PatternBindingDecl] var ... = ... -# 54| getInit(0): [ClosureExpr] { ... } +# 54| getInit(0): [ExplicitClosureExpr] { ... } # 54| getBody(): [BraceStmt] { ... } # 54| getElement(0): [ReturnStmt] return ... # 54| getResult(): [DeclRefExpr] x @@ -328,7 +328,7 @@ closures.swift: # 51| # 56| [Comment] // 42 # 56| -# 59| [ConcreteFuncDecl] bar() +# 59| [NamedFunction] bar() # 59| InterfaceType = () -> () -> Int # 59| getBody(): [BraceStmt] { ... } # 60| getElement(0): [PatternBindingDecl] var ... = ... @@ -337,7 +337,7 @@ closures.swift: # 60| getElement(1): [ConcreteVarDecl] x # 60| Type = Int # 61| getElement(2): [PatternBindingDecl] var ... = ... -# 61| getInit(0): [ClosureExpr] { ... } +# 61| getInit(0): [ExplicitClosureExpr] { ... } # 61| getParam(0): [ParamDecl] y # 61| Type = Int # 61| getBody(): [BraceStmt] { ... } @@ -367,7 +367,7 @@ closures.swift: # 62| getArgument(1): [Argument] : 40 # 62| getExpr(): [IntegerLiteralExpr] 40 # 63| getElement(5): [PatternBindingDecl] var ... = ... -# 63| getInit(0): [ClosureExpr] { ... } +# 63| getInit(0): [ExplicitClosureExpr] { ... } # 63| getBody(): [BraceStmt] { ... } # 63| getElement(0): [ReturnStmt] return ... # 63| getResult(): [DeclRefExpr] x @@ -395,7 +395,7 @@ closures.swift: # 68| getTypeRepr(): [TypeRepr] ((Int) -> Void)? # 68| [ConcreteVarDecl] g # 68| Type = ((Int) -> Void)? -# 69| [ConcreteFuncDecl] baz() +# 69| [NamedFunction] baz() # 69| InterfaceType = () -> () -> Int # 69| getBody(): [BraceStmt] { ... } # 70| getElement(0): [PatternBindingDecl] var ... = ... @@ -405,7 +405,7 @@ closures.swift: # 70| Type = Int # 71| getElement(2): [AssignExpr] ... = ... # 71| getDest(): [DeclRefExpr] g -# 71| getSource(): [ClosureExpr] { ... } +# 71| getSource(): [ExplicitClosureExpr] { ... } # 71| getParam(0): [ParamDecl] y # 71| Type = Int # 71| getBody(): [BraceStmt] { ... } @@ -433,7 +433,7 @@ closures.swift: # 72| getArgument(1): [Argument] : 40 # 72| getExpr(): [IntegerLiteralExpr] 40 # 73| getElement(4): [PatternBindingDecl] var ... = ... -# 73| getInit(0): [ClosureExpr] { ... } +# 73| getInit(0): [ExplicitClosureExpr] { ... } # 73| getBody(): [BraceStmt] { ... } # 73| getElement(0): [ReturnStmt] return ... # 73| getResult(): [DeclRefExpr] x @@ -455,7 +455,7 @@ closures.swift: # 70| # 71| [Comment] // closure escapes! # 71| -# 78| [ConcreteFuncDecl] quux() +# 78| [NamedFunction] quux() # 78| InterfaceType = () -> Int # 78| getBody(): [BraceStmt] { ... } # 79| getElement(0): [PatternBindingDecl] var ... = ... @@ -463,7 +463,7 @@ closures.swift: # 79| getPattern(0): [NamedPattern] y # 79| getElement(1): [ConcreteVarDecl] y # 79| Type = Int -# 81| getElement(2): [ConcreteFuncDecl] f() +# 81| getElement(2): [NamedFunction] f() # 81| InterfaceType = () -> () -> Void # 81| getBody(): [BraceStmt] { ... } # 82| getElement(0): [PatternBindingDecl] var ... = ... @@ -471,7 +471,7 @@ closures.swift: # 82| getPattern(0): [NamedPattern] x # 82| getElement(1): [ConcreteVarDecl] x # 82| Type = Int -# 84| getElement(2): [ConcreteFuncDecl] a() +# 84| getElement(2): [NamedFunction] a() # 84| InterfaceType = () -> () # 84| getBody(): [BraceStmt] { ... } # 85| getElement(0): [AssignExpr] ... = ... @@ -524,7 +524,7 @@ closures.swift: # 85| getCapture(0): [CapturedDecl] y # 85| getCapture(1): [CapturedDecl] x # 88| getCapture(2): [CapturedDecl] b() -# 92| getElement(3): [ConcreteFuncDecl] b() +# 92| getElement(3): [NamedFunction] b() # 92| InterfaceType = () -> () # 92| getBody(): [BraceStmt] { ... } # 93| getElement(0): [AssignExpr] ... = ... @@ -601,12 +601,12 @@ closures.swift: # 105| getResult().getFullyConverted(): [LoadExpr] (Int) ... # 105| [Comment] // 58341 # 105| -# 108| [ConcreteFuncDecl] sharedCapture() +# 108| [NamedFunction] sharedCapture() # 108| InterfaceType = () -> Int # 108| getBody(): [BraceStmt] { ... } # 109| getElement(0): [PatternBindingDecl] var ... = ... # 109| getInit(0): [CallExpr] call to ... -# 109| getFunction(): [ClosureExpr] { ... } +# 109| getFunction(): [ExplicitClosureExpr] { ... } # 109| getBody(): [BraceStmt] { ... } # 110| getElement(0): [PatternBindingDecl] var ... = ... # 110| getInit(0): [IntegerLiteralExpr] 0 @@ -615,7 +615,7 @@ closures.swift: # 110| Type = Int # 111| getElement(2): [ReturnStmt] return ... # 111| getResult(): [TupleExpr] (...) -# 111| getElement(0): [ClosureExpr] { ... } +# 111| getElement(0): [ExplicitClosureExpr] { ... } # 111| getBody(): [BraceStmt] { ... } # 111| getElement(0): [ReturnStmt] return ... # 111| getResult(): [BinaryExpr] ... .+=(_:_:) ... @@ -629,7 +629,7 @@ closures.swift: # 111| getArgument(1): [Argument] : 1 # 111| getExpr(): [IntegerLiteralExpr] 1 # 111| getCapture(0): [CapturedDecl] x -# 111| getElement(1): [ClosureExpr] { ... } +# 111| getElement(1): [ExplicitClosureExpr] { ... } # 111| getBody(): [BraceStmt] { ... } # 111| getElement(0): [ReturnStmt] return ... # 111| getResult(): [DeclRefExpr] x @@ -643,7 +643,7 @@ closures.swift: # 109| getElement(2): [ConcreteVarDecl] getX # 109| Type = () -> Int # 114| getElement(3): [PatternBindingDecl] var ... = ... -# 114| getInit(0): [ClosureExpr] { ... } +# 114| getInit(0): [ExplicitClosureExpr] { ... } # 114| getBody(): [BraceStmt] { ... } # 115| getElement(0): [CallExpr] call to ... # 115| getFunction(): [DeclRefExpr] incrX @@ -662,7 +662,7 @@ closures.swift: # 121| getFunction(): [DeclRefExpr] getX # 121| [Comment] // 4 # 121| -# 124| [ConcreteFuncDecl] sink(_:) +# 124| [NamedFunction] sink(_:) # 124| InterfaceType = (Int) -> () # 124| getParam(0): [ParamDecl] x # 124| Type = Int @@ -680,12 +680,12 @@ closures.swift: # 124| getExpr(): [DefaultArgumentExpr] default separator # 124| getArgument(2): [Argument] terminator: default terminator # 124| getExpr(): [DefaultArgumentExpr] default terminator -# 125| [ConcreteFuncDecl] source() +# 125| [NamedFunction] source() # 125| InterfaceType = () -> Int # 125| getBody(): [BraceStmt] { ... } # 125| getElement(0): [ReturnStmt] return ... # 125| getResult(): [IntegerLiteralExpr] -1 -# 127| [ConcreteFuncDecl] sharedCaptureMultipleWriters() +# 127| [NamedFunction] sharedCaptureMultipleWriters() # 127| InterfaceType = () -> () # 127| getBody(): [BraceStmt] { ... } # 128| getElement(0): [PatternBindingDecl] var ... = ... @@ -694,7 +694,7 @@ closures.swift: # 128| getElement(1): [ConcreteVarDecl] x # 128| Type = Int # 130| getElement(2): [PatternBindingDecl] var ... = ... -# 130| getInit(0): [ClosureExpr] { ... } +# 130| getInit(0): [ExplicitClosureExpr] { ... } # 130| getBody(): [BraceStmt] { ... } # 130| getElement(0): [ReturnStmt] return ... # 130| getResult(): [CallExpr] call to sink(_:) @@ -707,12 +707,12 @@ closures.swift: # 130| getElement(3): [ConcreteVarDecl] callSink # 130| Type = () -> () # 132| getElement(4): [PatternBindingDecl] var ... = ... -# 132| getInit(0): [ClosureExpr] { ... } +# 132| getInit(0): [ExplicitClosureExpr] { ... } # 132| getParam(0): [ParamDecl] y # 132| Type = Int # 132| getBody(): [BraceStmt] { ... } # 133| getElement(0): [PatternBindingDecl] var ... = ... -# 133| getInit(0): [ClosureExpr] { ... } +# 133| getInit(0): [ExplicitClosureExpr] { ... } # 133| getBody(): [BraceStmt] { ... } # 133| getElement(0): [ReturnStmt] return ... # 133| getResult(): [AssignExpr] ... = ... @@ -754,10 +754,10 @@ closures.swift: # 143| getFunction(): [DeclRefExpr] badSetter # 144| getElement(13): [CallExpr] call to ... # 144| getFunction(): [DeclRefExpr] callSink -# 147| [ConcreteFuncDecl] reentrant() +# 147| [NamedFunction] reentrant() # 147| InterfaceType = () -> Int # 147| getBody(): [BraceStmt] { ... } -# 149| getElement(0): [ConcreteFuncDecl] f(_:) +# 149| getElement(0): [NamedFunction] f(_:) # 149| InterfaceType = (Int) -> (Int) -> Int # 149| getParam(0): [ParamDecl] x # 149| Type = Int @@ -776,7 +776,7 @@ closures.swift: # 150| getExpr(): [IntegerLiteralExpr] 0 # 150| getThen(): [BraceStmt] { ... } # 151| getElement(0): [ReturnStmt] return ... -# 151| getResult(): [ClosureExpr] { ... } +# 151| getResult(): [ExplicitClosureExpr] { ... } # 151| getParam(0): [ParamDecl] _ # 151| Type = Int # 151| getBody(): [BraceStmt] { ... } @@ -800,7 +800,7 @@ closures.swift: # 154| getElement(2): [ConcreteVarDecl] next # 154| Type = (Int) -> Int # 155| getElement(3): [ReturnStmt] return ... -# 155| getResult(): [ClosureExpr] { ... } +# 155| getResult(): [ExplicitClosureExpr] { ... } # 155| getParam(0): [ParamDecl] k # 155| Type = Int # 155| getBody(): [BraceStmt] { ... } @@ -836,7 +836,7 @@ closures.swift: # 155| getCapture(0): [CapturedDecl] next # 155| getCapture(1): [CapturedDecl] x # 154| getCapture(0): [CapturedDecl] g(_:) -# 158| getElement(1): [ConcreteFuncDecl] g(_:) +# 158| getElement(1): [NamedFunction] g(_:) # 158| InterfaceType = (Int) -> (Int) -> Int # 158| getParam(0): [ParamDecl] x # 158| Type = Int @@ -855,7 +855,7 @@ closures.swift: # 159| getExpr(): [IntegerLiteralExpr] 0 # 159| getThen(): [BraceStmt] { ... } # 160| getElement(0): [ReturnStmt] return ... -# 160| getResult(): [ClosureExpr] { ... } +# 160| getResult(): [ExplicitClosureExpr] { ... } # 160| getParam(0): [ParamDecl] _ # 160| Type = Int # 160| getBody(): [BraceStmt] { ... } @@ -879,7 +879,7 @@ closures.swift: # 163| getElement(2): [ConcreteVarDecl] next # 163| Type = (Int) -> Int # 164| getElement(3): [ReturnStmt] return ... -# 164| getResult(): [ClosureExpr] { ... } +# 164| getResult(): [ExplicitClosureExpr] { ... } # 164| getParam(0): [ParamDecl] k # 164| Type = Int # 164| getBody(): [BraceStmt] { ... } @@ -943,7 +943,7 @@ closures.swift: # 171| getResult(): [DeclRefExpr] y # 171| [Comment] // 10004003085 # 171| -# 174| [ConcreteFuncDecl] main() +# 174| [NamedFunction] main() # 174| InterfaceType = () -> () # 174| getBody(): [BraceStmt] { ... } # 175| getElement(0): [CallExpr] call to print(_:separator:terminator:) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.expected b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.expected index 5300fb2dbbe..0e3d0d58aa0 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.expected +++ b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.expected @@ -1,22 +1,22 @@ -| var_decls.swift:4:7:4:7 | i | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | i | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:7:5:7:5 | numbers | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | [Int] | getNumberOfAccessorDecls: | 0 | getName: | numbers | getType: | [Int] | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:10:12:10:12 | numbers | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | [Int] | getNumberOfAccessorDecls: | 1 | getName: | numbers | getType: | [Int] | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 0 | -| var_decls.swift:15:7:15:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | T | getNumberOfAccessorDecls: | 3 | getName: | wrappedValue | getType: | T | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:20:7:20:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:24:15:24:15 | _wrapped | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | X | getNumberOfAccessorDecls: | 3 | getName: | _wrapped | getType: | X | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:24:15:24:15 | wrapped | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 3 | getName: | wrapped | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:28:7:28:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:34:7:34:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:35:7:35:7 | projectedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 3 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:39:7:39:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:40:7:40:7 | projectedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 3 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:54:10:54:10 | _w1 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | X | getNumberOfAccessorDecls: | 0 | getName: | _w1 | getType: | X | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:54:10:54:10 | w1 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 2 | getName: | w1 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:55:24:55:24 | _w2 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessorDecls: | 0 | getName: | _w2 | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:55:24:55:24 | w2 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 2 | getName: | w2 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:56:29:56:29 | $w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 2 | getName: | $w3 | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:56:29:56:29 | _w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | _w3 | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:56:29:56:29 | w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 2 | getName: | w3 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | getIntroducerInt: | 1 | -| var_decls.swift:57:36:57:36 | $w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 2 | getName: | $w4 | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:57:36:57:36 | _w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | _w4 | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | -| var_decls.swift:57:36:57:36 | w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 2 | getName: | w4 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | getIntroducerInt: | 1 | +| var_decls.swift:4:7:4:7 | i | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | i | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:7:5:7:5 | numbers | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | [Int] | getNumberOfAccessors: | 0 | getName: | numbers | getType: | [Int] | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:10:12:10:12 | numbers | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | [Int] | getNumberOfAccessors: | 1 | getName: | numbers | getType: | [Int] | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 0 | +| var_decls.swift:15:7:15:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | T | getNumberOfAccessors: | 3 | getName: | wrappedValue | getType: | T | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:20:7:20:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:24:15:24:15 | _wrapped | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | X | getNumberOfAccessors: | 3 | getName: | _wrapped | getType: | X | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:24:15:24:15 | wrapped | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 3 | getName: | wrapped | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:28:7:28:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:34:7:34:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:35:7:35:7 | projectedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 3 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:39:7:39:7 | wrappedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 3 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:40:7:40:7 | projectedValue | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 3 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:54:10:54:10 | _w1 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | X | getNumberOfAccessors: | 0 | getName: | _w1 | getType: | X | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:54:10:54:10 | w1 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 2 | getName: | w1 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:55:24:55:24 | _w2 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessors: | 0 | getName: | _w2 | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:55:24:55:24 | w2 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 2 | getName: | w2 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:56:29:56:29 | $w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 2 | getName: | $w3 | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:56:29:56:29 | _w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | _w3 | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:56:29:56:29 | w3 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 2 | getName: | w3 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | getIntroducerInt: | 1 | +| var_decls.swift:57:36:57:36 | $w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 2 | getName: | $w4 | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:57:36:57:36 | _w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | _w4 | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | getIntroducerInt: | 1 | +| var_decls.swift:57:36:57:36 | w4 | getModule: | file://:0:0:0:0 | var_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 2 | getName: | w4 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | yes | hasParentInitializer: | yes | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | getIntroducerInt: | 1 | diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql index 09261a1ef8c..6541a63eae8 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl.ql @@ -4,7 +4,7 @@ import TestUtils from ConcreteVarDecl x, ModuleDecl getModule, int getNumberOfMembers, Type getInterfaceType, - int getNumberOfAccessorDecls, string getName, Type getType, string hasAttachedPropertyWrapperType, + int getNumberOfAccessors, string getName, Type getType, string hasAttachedPropertyWrapperType, string hasParentPattern, string hasParentInitializer, string hasPropertyWrapperBackingVarBinding, string hasPropertyWrapperBackingVar, string hasPropertyWrapperProjectionVarBinding, string hasPropertyWrapperProjectionVar, int getIntroducerInt @@ -14,7 +14,7 @@ where getModule = x.getModule() and getNumberOfMembers = x.getNumberOfMembers() and getInterfaceType = x.getInterfaceType() and - getNumberOfAccessorDecls = x.getNumberOfAccessorDecls() and + getNumberOfAccessors = x.getNumberOfAccessors() and getName = x.getName() and getType = x.getType() and ( @@ -46,9 +46,9 @@ where ) and getIntroducerInt = x.getIntroducerInt() select x, "getModule:", getModule, "getNumberOfMembers:", getNumberOfMembers, "getInterfaceType:", - getInterfaceType, "getNumberOfAccessorDecls:", getNumberOfAccessorDecls, "getName:", getName, - "getType:", getType, "hasAttachedPropertyWrapperType:", hasAttachedPropertyWrapperType, - "hasParentPattern:", hasParentPattern, "hasParentInitializer:", hasParentInitializer, + getInterfaceType, "getNumberOfAccessors:", getNumberOfAccessors, "getName:", getName, "getType:", + getType, "hasAttachedPropertyWrapperType:", hasAttachedPropertyWrapperType, "hasParentPattern:", + hasParentPattern, "hasParentInitializer:", hasParentInitializer, "hasPropertyWrapperBackingVarBinding:", hasPropertyWrapperBackingVarBinding, "hasPropertyWrapperBackingVar:", hasPropertyWrapperBackingVar, "hasPropertyWrapperProjectionVarBinding:", hasPropertyWrapperProjectionVarBinding, diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.expected b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.expected rename to swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.ql b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.ql similarity index 79% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.ql rename to swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.ql index b25caf7bf97..20c7337f493 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessorDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/ConcreteVarDecl_getAccessor.ql @@ -4,4 +4,4 @@ import TestUtils from ConcreteVarDecl x, int index where toBeTested(x) and not x.isUnknown() -select x, index, x.getAccessorDecl(index) +select x, index, x.getAccessor(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/Deinitializer/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConstructorDecl/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/decl/Deinitializer/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/decl/Initializer/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/DestructorDecl/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/decl/Initializer/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.ql similarity index 91% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.ql index 509f63fcc9f..438adc451d4 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction.ql @@ -3,7 +3,7 @@ import codeql.swift.elements import TestUtils from - ConcreteFuncDecl x, string hasName, string hasSelfParam, int getNumberOfParams, string hasBody, + NamedFunction x, string hasName, string hasSelfParam, int getNumberOfParams, string hasBody, int getNumberOfCaptures, int getNumberOfGenericTypeParams, ModuleDecl getModule, int getNumberOfMembers, Type getInterfaceType where diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.ql similarity index 85% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.ql index 5a5a36820e9..cd68b79b74c 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getBody.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getBody.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x +from NamedFunction x where toBeTested(x) and not x.isUnknown() select x, x.getBody() diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.ql similarity index 82% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.ql index 5f3bfa1a66f..3ada6243aac 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getCapture.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getCapture.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x, int index +from NamedFunction x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getCapture(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.ql similarity index 82% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.ql index 09138d68fcc..3006ec840a0 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getGenericTypeParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getGenericTypeParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x, int index +from NamedFunction x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getGenericTypeParam(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.ql similarity index 82% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.ql index d355f662c1c..7155c70acf0 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getMember.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getMember.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x, int index +from NamedFunction x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getMember(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.ql similarity index 85% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.ql index 7ccb2e93c4f..e929141fab0 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getName.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getName.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x +from NamedFunction x where toBeTested(x) and not x.isUnknown() select x, x.getName() diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.ql similarity index 81% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.ql index a1cd6846487..6e0b66c4bc1 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x, int index +from NamedFunction x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getParam(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.expected b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.expected rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.ql b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.ql similarity index 86% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.ql rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.ql index f5ba5c8592e..8f272ed8c62 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/ConcreteFuncDecl_getSelfParam.ql +++ b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/NamedFunction_getSelfParam.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConcreteFuncDecl x +from NamedFunction x where toBeTested(x) and not x.isUnknown() select x, x.getSelfParam() diff --git a/swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/functions.swift b/swift/ql/test/extractor-tests/generated/decl/NamedFunction/functions.swift similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ConcreteFuncDecl/functions.swift rename to swift/ql/test/extractor-tests/generated/decl/NamedFunction/functions.swift diff --git a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.expected b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.expected index 1718a8300ee..a83bdc80b26 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.expected +++ b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.expected @@ -1,63 +1,63 @@ -| file://:0:0:0:0 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| file://:0:0:0:0 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:1:10:1:13 | _ | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | _ | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:1:18:1:29 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Double | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Double | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:2:10:2:13 | _ | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | _ | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:2:18:2:29 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Double | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Double | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:4:8:4:8 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:5:5:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:15:5:15 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:15:5:15 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:15:5:18 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:23:5:23 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:23:5:23 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:5:23:5:26 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:6:9:6:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:7:9:7:9 | newValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int? | getNumberOfAccessorDecls: | 0 | getName: | newValue | getType: | Int? | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:7:9:7:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:12:13:12:22 | s | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | String | getNumberOfAccessorDecls: | 0 | getName: | s | getType: | String | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:13:13:13:22 | s | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | String | getNumberOfAccessorDecls: | 0 | getName: | s | getType: | String | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:14:26:14:26 | $0 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | $0 | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:17:25:17:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:17:25:17:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:17:25:17:25 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:18:9:18:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:22:9:22:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:24:5:24:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:24:10:24:24 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:27:25:27:25 | projectedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:27:25:27:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:27:25:27:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:27:25:27:25 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:28:9:28:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:29:9:29:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:33:9:33:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:34:9:34:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:36:5:36:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:36:10:36:24 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:41:5:41:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessorDecls: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:41:10:41:26 | projectedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:48:18:48:22 | p1 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | p1 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | -| param_decls.swift:49:26:49:30 | p2 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | p2 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | -| param_decls.swift:50:31:50:31 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:50:31:50:35 | p3 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | p3 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | -| param_decls.swift:51:38:51:38 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessorDecls: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | -| param_decls.swift:51:38:51:42 | p4 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessorDecls: | 0 | getName: | p4 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | +| file://:0:0:0:0 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| file://:0:0:0:0 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:1:10:1:13 | _ | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | _ | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:1:18:1:29 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Double | getNumberOfAccessors: | 0 | getName: | y | getType: | Double | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:2:10:2:13 | _ | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | _ | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:2:18:2:29 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Double | getNumberOfAccessors: | 0 | getName: | y | getType: | Double | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:4:8:4:8 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessors: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:5:5:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessors: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:15:5:15 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:15:5:15 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:15:5:18 | x | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | x | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:23:5:23 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:23:5:23 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:5:23:5:26 | y | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | y | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:6:9:6:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessors: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:7:9:7:9 | newValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int? | getNumberOfAccessors: | 0 | getName: | newValue | getType: | Int? | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:7:9:7:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | S | getNumberOfAccessors: | 0 | getName: | self | getType: | S | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:12:13:12:22 | s | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | String | getNumberOfAccessors: | 0 | getName: | s | getType: | String | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:13:13:13:22 | s | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | String | getNumberOfAccessors: | 0 | getName: | s | getType: | String | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:14:26:14:26 | $0 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | $0 | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:17:25:17:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessors: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:17:25:17:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessors: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:17:25:17:25 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessors: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessors: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:18:9:18:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Wrapper | getNumberOfAccessors: | 0 | getName: | self | getType: | Wrapper | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:18:9:18:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:22:9:22:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:22:9:22:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:24:5:24:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:24:10:24:24 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:27:25:27:25 | projectedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:27:25:27:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:27:25:27:25 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:27:25:27:25 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:28:9:28:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:28:9:28:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:29:9:29:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjected | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjected | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:29:9:29:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:33:9:33:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:33:9:33:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | value | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:34:9:34:9 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:34:9:34:9 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:36:5:36:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:36:10:36:24 | wrappedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | wrappedValue | getType: | Int | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:41:5:41:5 | self | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | WrapperWithProjectedAndInit | getNumberOfAccessors: | 0 | getName: | self | getType: | WrapperWithProjectedAndInit | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | yes | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:41:10:41:26 | projectedValue | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | projectedValue | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:48:18:48:22 | p1 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | p1 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | +| param_decls.swift:49:26:49:30 | p2 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | p2 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | yes | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | +| param_decls.swift:50:31:50:31 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:50:31:50:35 | p3 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | p3 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | +| param_decls.swift:51:38:51:38 | value | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Bool | getNumberOfAccessors: | 0 | getName: | value | getType: | Bool | hasAttachedPropertyWrapperType: | no | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | no | hasPropertyWrapperProjectionVarBinding: | no | hasPropertyWrapperProjectionVar: | no | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | no | +| param_decls.swift:51:38:51:42 | p4 | getModule: | file://:0:0:0:0 | param_decls | getNumberOfMembers: | 0 | getInterfaceType: | Int | getNumberOfAccessors: | 0 | getName: | p4 | getType: | Int | hasAttachedPropertyWrapperType: | yes | hasParentPattern: | no | hasParentInitializer: | no | hasPropertyWrapperBackingVarBinding: | no | hasPropertyWrapperBackingVar: | yes | hasPropertyWrapperProjectionVarBinding: | yes | hasPropertyWrapperProjectionVar: | yes | isInout: | no | hasPropertyWrapperLocalWrappedVarBinding: | no | hasPropertyWrapperLocalWrappedVar: | yes | diff --git a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql index af0351abcaf..6a6562ed8b1 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl.ql @@ -4,7 +4,7 @@ import TestUtils from ParamDecl x, ModuleDecl getModule, int getNumberOfMembers, Type getInterfaceType, - int getNumberOfAccessorDecls, string getName, Type getType, string hasAttachedPropertyWrapperType, + int getNumberOfAccessors, string getName, Type getType, string hasAttachedPropertyWrapperType, string hasParentPattern, string hasParentInitializer, string hasPropertyWrapperBackingVarBinding, string hasPropertyWrapperBackingVar, string hasPropertyWrapperProjectionVarBinding, string hasPropertyWrapperProjectionVar, string isInout, @@ -15,7 +15,7 @@ where getModule = x.getModule() and getNumberOfMembers = x.getNumberOfMembers() and getInterfaceType = x.getInterfaceType() and - getNumberOfAccessorDecls = x.getNumberOfAccessorDecls() and + getNumberOfAccessors = x.getNumberOfAccessors() and getName = x.getName() and getType = x.getType() and ( @@ -55,9 +55,9 @@ where then hasPropertyWrapperLocalWrappedVar = "yes" else hasPropertyWrapperLocalWrappedVar = "no" select x, "getModule:", getModule, "getNumberOfMembers:", getNumberOfMembers, "getInterfaceType:", - getInterfaceType, "getNumberOfAccessorDecls:", getNumberOfAccessorDecls, "getName:", getName, - "getType:", getType, "hasAttachedPropertyWrapperType:", hasAttachedPropertyWrapperType, - "hasParentPattern:", hasParentPattern, "hasParentInitializer:", hasParentInitializer, + getInterfaceType, "getNumberOfAccessors:", getNumberOfAccessors, "getName:", getName, "getType:", + getType, "hasAttachedPropertyWrapperType:", hasAttachedPropertyWrapperType, "hasParentPattern:", + hasParentPattern, "hasParentInitializer:", hasParentInitializer, "hasPropertyWrapperBackingVarBinding:", hasPropertyWrapperBackingVarBinding, "hasPropertyWrapperBackingVar:", hasPropertyWrapperBackingVar, "hasPropertyWrapperProjectionVarBinding:", hasPropertyWrapperProjectionVarBinding, diff --git a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.expected b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.expected rename to swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.expected diff --git a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.ql b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.ql similarity index 78% rename from swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.ql rename to swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.ql index a751e0006cc..8802b9d76ba 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessorDecl.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ParamDecl/ParamDecl_getAccessor.ql @@ -4,4 +4,4 @@ import TestUtils from ParamDecl x, int index where toBeTested(x) and not x.isUnknown() -select x, index, x.getAccessorDecl(index) +select x, index, x.getAccessor(index) diff --git a/swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/ExplicitClosureExpr/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/ClosureExpr/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/expr/ExplicitClosureExpr/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.expected b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.expected rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.expected diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.ql b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.ql similarity index 88% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.ql rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.ql index 90162a53909..45aba0d0d17 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr.ql +++ b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr.ql @@ -3,7 +3,7 @@ import codeql.swift.elements import TestUtils from - ConstructorRefCallExpr x, string hasType, Expr getFunction, int getNumberOfArguments, Expr getBase + InitializerRefCallExpr x, string hasType, Expr getFunction, int getNumberOfArguments, Expr getBase where toBeTested(x) and not x.isUnknown() and diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.expected b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.expected rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.expected diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.ql similarity index 79% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.ql index a7aa90afb8f..19c63285bfb 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getArgument.ql +++ b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getArgument.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConstructorRefCallExpr x, int index +from InitializerRefCallExpr x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getArgument(index) diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.expected b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.expected similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.expected rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.expected diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.ql similarity index 82% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.ql index 209c4f58f8b..c9379c517ae 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/ConstructorRefCallExpr_getType.ql +++ b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/InitializerRefCallExpr_getType.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ConstructorRefCallExpr x +from InitializerRefCallExpr x where toBeTested(x) and not x.isUnknown() select x, x.getType() diff --git a/swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/constructor_ref_calls.swift b/swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/initializer_ref_calls.swift similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/ConstructorRefCallExpr/constructor_ref_calls.swift rename to swift/ql/test/extractor-tests/generated/expr/InitializerRefCallExpr/initializer_ref_calls.swift diff --git a/swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/LazyInitializationExpr/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/expr/LazyInitializationExpr/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/OtherInitializerRefExpr/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/OtherConstructorDeclRefExpr/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/expr/OtherInitializerRefExpr/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt b/swift/ql/test/extractor-tests/generated/expr/RebindSelfInInitializerExpr/MISSING_SOURCE.txt similarity index 100% rename from swift/ql/test/extractor-tests/generated/expr/RebindSelfInConstructorExpr/MISSING_SOURCE.txt rename to swift/ql/test/extractor-tests/generated/expr/RebindSelfInInitializerExpr/MISSING_SOURCE.txt diff --git a/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql index f0f6c90f879..cfb94bd7d37 100644 --- a/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql +++ b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql @@ -1,6 +1,6 @@ import codeql.swift.elements -from FuncDecl f, AnyFunctionType t, string s +from Function f, AnyFunctionType t, string s where f.getInterfaceType() = t and f.getLocation().getFile().getName().matches("%swift/ql/test%") and diff --git a/swift/ql/test/library-tests/ast/PrintAst.expected b/swift/ql/test/library-tests/ast/PrintAst.expected index a8bf92c277c..f1d3c7dba9b 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.expected +++ b/swift/ql/test/library-tests/ast/PrintAst.expected @@ -23,7 +23,7 @@ cfg.swift: # 3| getExpr().getFullyConverted(): [LoadExpr] (Int) ... # 3| getArgument(1): [Argument] : 1 # 3| getExpr(): [IntegerLiteralExpr] 1 -# 5| [ConcreteFuncDecl] returnZero() +# 5| [NamedFunction] returnZero() # 5| InterfaceType = () -> Int # 5| getBody(): [BraceStmt] { ... } # 5| getElement(0): [ReturnStmt] return ... @@ -50,7 +50,7 @@ cfg.swift: # 12| getMember(4): [EnumElementDecl] error3 # 12| getParam(0): [ParamDecl] withParam # 12| Type = Int -# 15| [ConcreteFuncDecl] isZero(x:) +# 15| [NamedFunction] isZero(x:) # 15| InterfaceType = (Int) -> Bool # 15| getParam(0): [ParamDecl] x # 15| Type = Int @@ -65,7 +65,7 @@ cfg.swift: # 15| getExpr(): [DeclRefExpr] x # 15| getArgument(1): [Argument] : 0 # 15| getExpr(): [IntegerLiteralExpr] 0 -# 17| [ConcreteFuncDecl] mightThrow(x:) +# 17| [NamedFunction] mightThrow(x:) # 17| InterfaceType = (Int) throws -> Void # 17| getParam(0): [ParamDecl] x # 17| Type = Int @@ -119,7 +119,7 @@ cfg.swift: # 22| getArgument(1): [Argument] : 1 # 22| getExpr(): [IntegerLiteralExpr] 1 # 22| getSubExpr().getFullyConverted(): [ErasureExpr] (Error) ... -# 26| [ConcreteFuncDecl] tryCatch(x:) +# 26| [NamedFunction] tryCatch(x:) # 26| InterfaceType = (Int) -> Int # 26| getParam(0): [ParamDecl] x # 26| Type = Int @@ -248,13 +248,13 @@ cfg.swift: # 35| Type = Int # 39| [ConcreteVarDecl] error # 39| Type = Error -# 45| [ConcreteFuncDecl] createClosure1(s:) +# 45| [NamedFunction] createClosure1(s:) # 45| InterfaceType = (String) -> () -> String # 45| getParam(0): [ParamDecl] s # 45| Type = String # 45| getBody(): [BraceStmt] { ... } # 46| getElement(0): [ReturnStmt] return ... -# 46| getResult(): [ClosureExpr] { ... } +# 46| getResult(): [ExplicitClosureExpr] { ... } # 46| getBody(): [BraceStmt] { ... } # 47| getElement(0): [ReturnStmt] return ... # 47| getResult(): [BinaryExpr] ... .+(_:_:) ... @@ -267,12 +267,12 @@ cfg.swift: # 47| getArgument(1): [Argument] : # 47| getExpr(): [StringLiteralExpr] # 47| getCapture(0): [CapturedDecl] s -# 51| [ConcreteFuncDecl] createClosure2(x:) +# 51| [NamedFunction] createClosure2(x:) # 51| InterfaceType = (Int) -> (Int) -> Int # 51| getParam(0): [ParamDecl] x # 51| Type = Int # 51| getBody(): [BraceStmt] { ... } -# 52| getElement(0): [ConcreteFuncDecl] f(y:) +# 52| getElement(0): [NamedFunction] f(y:) # 52| InterfaceType = (Int) -> Int # 52| getParam(0): [ParamDecl] y # 52| Type = Int @@ -290,13 +290,13 @@ cfg.swift: # 53| getCapture(0): [CapturedDecl] x # 55| getElement(1): [ReturnStmt] return ... # 55| getResult(): [DeclRefExpr] f(y:) -# 58| [ConcreteFuncDecl] createClosure3(x:) +# 58| [NamedFunction] createClosure3(x:) # 58| InterfaceType = (Int) -> (Int) -> Int # 58| getParam(0): [ParamDecl] x # 58| Type = Int # 58| getBody(): [BraceStmt] { ... } # 59| getElement(0): [ReturnStmt] return ... -# 59| getResult(): [ClosureExpr] { ... } +# 59| getResult(): [ExplicitClosureExpr] { ... } # 60| getParam(0): [ParamDecl] y # 60| Type = Int # 59| getBody(): [BraceStmt] { ... } @@ -311,7 +311,7 @@ cfg.swift: # 60| getArgument(1): [Argument] : y # 60| getExpr(): [DeclRefExpr] y # 60| getCapture(0): [CapturedDecl] x -# 64| [ConcreteFuncDecl] callClosures() +# 64| [NamedFunction] callClosures() # 64| InterfaceType = () -> () # 64| getBody(): [BraceStmt] { ... } # 65| getElement(0): [PatternBindingDecl] var ... = ... @@ -345,7 +345,7 @@ cfg.swift: # 67| getPattern(0): [NamedPattern] x3 # 67| getElement(5): [ConcreteVarDecl] x3 # 67| Type = Int -# 70| [ConcreteFuncDecl] maybeParseInt(s:) +# 70| [NamedFunction] maybeParseInt(s:) # 70| InterfaceType = (String) -> Int? # 70| getParam(0): [ParamDecl] s # 70| Type = String @@ -366,7 +366,7 @@ cfg.swift: # 72| getElement(2): [ReturnStmt] return ... # 72| getResult(): [DeclRefExpr] n # 72| getResult().getFullyConverted(): [LoadExpr] (Int?) ... -# 75| [ConcreteFuncDecl] forceAndBackToOptional() +# 75| [NamedFunction] forceAndBackToOptional() # 75| InterfaceType = () -> Int? # 75| getBody(): [BraceStmt] { ... } # 76| getElement(0): [PatternBindingDecl] var ... = ... @@ -400,7 +400,7 @@ cfg.swift: # 78| getSubExpr(): [DeclRefExpr] n # 78| getSubExpr().getFullyConverted(): [LoadExpr] (Int?) ... # 78| getResult().getFullyConverted(): [InjectIntoOptionalExpr] (Int?) ... -# 81| [ConcreteFuncDecl] testInOut() +# 81| [NamedFunction] testInOut() # 81| InterfaceType = () -> Int # 81| getBody(): [BraceStmt] { ... } # 82| getElement(0): [PatternBindingDecl] var ... = ... @@ -408,7 +408,7 @@ cfg.swift: # 82| getPattern(0): [NamedPattern] temp # 82| getElement(1): [ConcreteVarDecl] temp # 82| Type = Int -# 84| getElement(2): [ConcreteFuncDecl] add(a:) +# 84| getElement(2): [NamedFunction] add(a:) # 84| InterfaceType = (inout Int) -> () # 84| getParam(0): [ParamDecl] a # 84| Type = Int @@ -425,7 +425,7 @@ cfg.swift: # 85| getExpr().getFullyConverted(): [LoadExpr] (Int) ... # 85| getArgument(1): [Argument] : 1 # 85| getExpr(): [IntegerLiteralExpr] 1 -# 88| getElement(3): [ConcreteFuncDecl] addOptional(a:) +# 88| getElement(3): [NamedFunction] addOptional(a:) # 88| InterfaceType = (inout Int?) -> () # 88| getParam(0): [ParamDecl] a # 88| Type = Int? @@ -471,7 +471,7 @@ cfg.swift: # 99| getTypeRepr(): [TypeRepr] Int # 99| getMember(1): [ConcreteVarDecl] myInt # 99| Type = Int -# 99| getAccessorDecl(0): [AccessorDecl] get +# 99| getAccessor(0): [Accessor] get # 99| InterfaceType = (C) -> () -> Int # 99| getSelfParam(): [ParamDecl] self # 99| Type = C @@ -479,7 +479,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .myInt #-----| getBase(): [DeclRefExpr] self -# 100| getMember(2): [ConstructorDecl] C.init(n:) +# 100| getMember(2): [Initializer] C.init(n:) # 100| InterfaceType = (C.Type) -> (Int) -> C # 100| getSelfParam(): [ParamDecl] self # 100| Type = C @@ -491,7 +491,7 @@ cfg.swift: # 101| getBase(): [DeclRefExpr] self # 101| getSource(): [DeclRefExpr] n # 102| getElement(1): [ReturnStmt] return -# 104| getMember(3): [ConcreteFuncDecl] getMyInt() +# 104| getMember(3): [NamedFunction] getMyInt() # 104| InterfaceType = (C) -> () -> Int # 104| getSelfParam(): [ParamDecl] self # 104| Type = C @@ -499,12 +499,12 @@ cfg.swift: # 105| getElement(0): [ReturnStmt] return ... # 105| getResult(): [MemberRefExpr] .myInt # 105| getBase(): [DeclRefExpr] self -# 98| getMember(4): [DestructorDecl] C.deinit() +# 98| getMember(4): [Deinitializer] C.deinit() # 98| InterfaceType = (C) -> () -> () # 98| getSelfParam(): [ParamDecl] self # 98| Type = C # 98| getBody(): [BraceStmt] { ... } -# 109| [ConcreteFuncDecl] testMemberRef(param:inoutParam:opt:) +# 109| [NamedFunction] testMemberRef(param:inoutParam:opt:) # 109| InterfaceType = (C, inout C, C?) -> () # 109| getParam(0): [ParamDecl] param # 109| Type = C @@ -694,7 +694,7 @@ cfg.swift: # 134| getPattern(0): [NamedPattern] n20 # 134| getElement(41): [ConcreteVarDecl] n20 # 134| Type = Int? -# 137| [ConcreteFuncDecl] patterns(x:) +# 137| [NamedFunction] patterns(x:) # 137| InterfaceType = (Int) -> Bool # 137| getParam(0): [ParamDecl] x # 137| Type = Int @@ -823,7 +823,7 @@ cfg.swift: # 159| getResult(): [BooleanLiteralExpr] false # 156| [ConcreteVarDecl] x # 156| Type = (Int) -# 163| [ConcreteFuncDecl] testDefer(x:) +# 163| [NamedFunction] testDefer(x:) # 163| InterfaceType = (inout Int) -> () # 163| getParam(0): [ParamDecl] x # 163| Type = Int @@ -882,7 +882,7 @@ cfg.swift: # 176| getExpr(): [DefaultArgumentExpr] default terminator # 164| [Comment] // Will print 1, 2, 3, 4 # 164| -# 181| [ConcreteFuncDecl] m1(x:) +# 181| [NamedFunction] m1(x:) # 181| InterfaceType = (Int) -> () # 181| getParam(0): [ParamDecl] x # 181| Type = Int @@ -994,7 +994,7 @@ cfg.swift: # 189| getExpr(): [DefaultArgumentExpr] default separator # 189| getArgument(2): [Argument] terminator: default terminator # 189| getExpr(): [DefaultArgumentExpr] default terminator -# 193| [ConcreteFuncDecl] m2(b:) +# 193| [NamedFunction] m2(b:) # 193| InterfaceType = (Bool) -> Int # 193| getParam(0): [ParamDecl] b # 193| Type = Bool @@ -1008,7 +1008,7 @@ cfg.swift: # 195| getResult(): [IntegerLiteralExpr] 0 # 197| getElement(1): [ReturnStmt] return ... # 197| getResult(): [IntegerLiteralExpr] 1 -# 200| [ConcreteFuncDecl] m3(x:) +# 200| [NamedFunction] m3(x:) # 200| InterfaceType = (inout Int) -> Int # 200| getParam(0): [ParamDecl] x # 200| Type = Int @@ -1066,7 +1066,7 @@ cfg.swift: # 207| getElement(1): [ReturnStmt] return ... # 207| getResult(): [DeclRefExpr] x # 207| getResult().getFullyConverted(): [LoadExpr] (Int) ... -# 210| [ConcreteFuncDecl] m4(b1:b2:b3:) +# 210| [NamedFunction] m4(b1:b2:b3:) # 210| InterfaceType = (Bool, Bool, Bool) -> String # 210| getParam(0): [ParamDecl] b1 # 210| Type = Bool @@ -1084,7 +1084,7 @@ cfg.swift: # 211| getCondition().getFullyConverted(): [ParenExpr] (...) # 211| getThenExpr(): [StringLiteralExpr] b2 || b3 # 211| getElseExpr(): [StringLiteralExpr] !b2 || !b3 -# 214| [ConcreteFuncDecl] conversionsInSplitEntry(b:) +# 214| [NamedFunction] conversionsInSplitEntry(b:) # 214| InterfaceType = (Bool) -> String # 214| getParam(0): [ParamDecl] b # 214| Type = Bool @@ -1104,7 +1104,7 @@ cfg.swift: # 218| getElse(): [BraceStmt] { ... } # 219| getElement(0): [ReturnStmt] return ... # 219| getResult(): [StringLiteralExpr] !b -# 223| [ConcreteFuncDecl] constant_condition() +# 223| [NamedFunction] constant_condition() # 223| InterfaceType = () -> () # 223| getBody(): [BraceStmt] { ... } # 224| getElement(0): [IfStmt] if ... then { ... } @@ -1129,7 +1129,7 @@ cfg.swift: # 225| getExpr(): [DefaultArgumentExpr] default separator # 225| getArgument(2): [Argument] terminator: default terminator # 225| getExpr(): [DefaultArgumentExpr] default terminator -# 229| [ConcreteFuncDecl] empty_else(b:) +# 229| [NamedFunction] empty_else(b:) # 229| InterfaceType = (Bool) -> () # 229| getParam(0): [ParamDecl] b # 229| Type = Bool @@ -1162,7 +1162,7 @@ cfg.swift: # 234| getExpr(): [DefaultArgumentExpr] default separator # 234| getArgument(2): [Argument] terminator: default terminator # 234| getExpr(): [DefaultArgumentExpr] default terminator -# 237| [ConcreteFuncDecl] disjunct(b1:b2:) +# 237| [NamedFunction] disjunct(b1:b2:) # 237| InterfaceType = (Bool, Bool) -> () # 237| getParam(0): [ParamDecl] b1 # 237| Type = Bool @@ -1198,7 +1198,7 @@ cfg.swift: # 239| getExpr(): [DefaultArgumentExpr] default separator # 239| getArgument(2): [Argument] terminator: default terminator # 239| getExpr(): [DefaultArgumentExpr] default terminator -# 243| [ConcreteFuncDecl] binaryExprs(a:b:) +# 243| [NamedFunction] binaryExprs(a:b:) # 243| InterfaceType = (Int, Int) -> () # 243| getParam(0): [ParamDecl] a # 243| Type = Int @@ -1413,7 +1413,7 @@ cfg.swift: # 259| getPattern(0): [NamedPattern] t # 259| getElement(31): [ConcreteVarDecl] t # 259| Type = Bool -# 262| [ConcreteFuncDecl] interpolatedString(x:y:) +# 262| [NamedFunction] interpolatedString(x:y:) # 262| InterfaceType = (Int, Int) -> String # 262| getParam(0): [ParamDecl] x # 262| Type = Int @@ -1501,7 +1501,7 @@ cfg.swift: #-----| getMethodRef(): [DeclRefExpr] appendLiteral(_:) # 263| getArgument(0): [Argument] : # 263| getExpr(): [StringLiteralExpr] -# 266| [ConcreteFuncDecl] testSubscriptExpr() +# 266| [NamedFunction] testSubscriptExpr() # 266| InterfaceType = () -> (Int, Int, Int, Int, Int) # 266| getBody(): [BraceStmt] { ... } # 267| getElement(0): [PatternBindingDecl] var ... = ... @@ -2022,7 +2022,7 @@ cfg.swift: # 296| getArgument(0): [Argument] : 4 # 296| getExpr(): [IntegerLiteralExpr] 4 # 296| getExpr().getFullyConverted(): [LoadExpr] (Int) ... -# 299| [ConcreteFuncDecl] loop1(x:) +# 299| [NamedFunction] loop1(x:) # 299| InterfaceType = (inout Int) -> () # 299| getParam(0): [ParamDecl] x # 299| Type = Int @@ -2063,7 +2063,7 @@ cfg.swift: # 302| getSubExpr(): [DeclRefExpr] x # 302| getArgument(1): [Argument] : 1 # 302| getExpr(): [IntegerLiteralExpr] 1 -# 306| [ConcreteFuncDecl] loop2(x:) +# 306| [NamedFunction] loop2(x:) # 306| InterfaceType = (inout Int) -> () # 306| getParam(0): [ParamDecl] x # 306| Type = Int @@ -2156,7 +2156,7 @@ cfg.swift: # 318| getExpr(): [DefaultArgumentExpr] default separator # 318| getArgument(2): [Argument] terminator: default terminator # 318| getExpr(): [DefaultArgumentExpr] default terminator -# 321| [ConcreteFuncDecl] labeledLoop(x:) +# 321| [NamedFunction] labeledLoop(x:) # 321| InterfaceType = (inout Int) -> () # 321| getParam(0): [ParamDecl] x # 321| Type = Int @@ -2263,7 +2263,7 @@ cfg.swift: # 334| getExpr(): [DefaultArgumentExpr] default separator # 334| getArgument(2): [Argument] terminator: default terminator # 334| getExpr(): [DefaultArgumentExpr] default terminator -# 338| [ConcreteFuncDecl] testRepeat(x:) +# 338| [NamedFunction] testRepeat(x:) # 338| InterfaceType = (inout Int) -> () # 338| getParam(0): [ParamDecl] x # 338| Type = Int @@ -2302,7 +2302,7 @@ cfg.swift: # 341| getSubExpr(): [DeclRefExpr] x # 341| getArgument(1): [Argument] : 1 # 341| getExpr(): [IntegerLiteralExpr] 1 -# 345| [ConcreteFuncDecl] loop_with_identity_expr() +# 345| [NamedFunction] loop_with_identity_expr() # 345| InterfaceType = () -> () # 345| getBody(): [BraceStmt] { ... } # 346| getElement(0): [PatternBindingDecl] var ... = ... @@ -2342,7 +2342,7 @@ cfg.swift: # 353| getTypeRepr(): [TypeRepr] C? # 353| getMember(1): [ConcreteVarDecl] c # 353| Type = C? -# 353| getAccessorDecl(0): [AccessorDecl] get +# 353| getAccessor(0): [Accessor] get # 353| InterfaceType = (OptionalC) -> () -> C? # 353| getSelfParam(): [ParamDecl] self # 353| Type = OptionalC @@ -2350,7 +2350,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .c #-----| getBase(): [DeclRefExpr] self -# 354| getMember(2): [ConstructorDecl] OptionalC.init(arg:) +# 354| getMember(2): [Initializer] OptionalC.init(arg:) # 354| InterfaceType = (OptionalC.Type) -> (C?) -> OptionalC # 354| getSelfParam(): [ParamDecl] self # 354| Type = OptionalC @@ -2362,7 +2362,7 @@ cfg.swift: # 355| getBase(): [DeclRefExpr] self # 355| getSource(): [DeclRefExpr] arg # 356| getElement(1): [ReturnStmt] return -# 358| getMember(3): [ConcreteFuncDecl] getOptional() +# 358| getMember(3): [NamedFunction] getOptional() # 358| InterfaceType = (OptionalC) -> () -> C? # 358| getSelfParam(): [ParamDecl] self # 358| Type = OptionalC @@ -2370,12 +2370,12 @@ cfg.swift: # 359| getElement(0): [ReturnStmt] return ... # 359| getResult(): [MemberRefExpr] .c # 359| getBase(): [DeclRefExpr] self -# 352| getMember(4): [DestructorDecl] OptionalC.deinit() +# 352| getMember(4): [Deinitializer] OptionalC.deinit() # 352| InterfaceType = (OptionalC) -> () -> () # 352| getSelfParam(): [ParamDecl] self # 352| Type = OptionalC # 352| getBody(): [BraceStmt] { ... } -# 363| [ConcreteFuncDecl] testOptional(c:) +# 363| [NamedFunction] testOptional(c:) # 363| InterfaceType = (OptionalC?) -> Int? # 363| getParam(0): [ParamDecl] c # 363| Type = OptionalC? @@ -2392,7 +2392,7 @@ cfg.swift: # 364| getMethodRef(): [DeclRefExpr] getOptional() # 364| getMethodRef(): [DeclRefExpr] getMyInt() # 364| getSubExpr().getFullyConverted(): [InjectIntoOptionalExpr] (Int?) ... -# 367| [ConcreteFuncDecl] testCapture(x:y:) +# 367| [NamedFunction] testCapture(x:y:) # 367| InterfaceType = (Int, Int) -> () -> Int # 367| getParam(0): [ParamDecl] x # 367| Type = Int @@ -2415,14 +2415,14 @@ cfg.swift: # 368| getBindingDecl(1): [PatternBindingDecl] var ... = ... # 368| getInit(0): [StringLiteralExpr] literal # 368| getPattern(0): [NamedPattern] t -# 368| getClosureBody(): [ClosureExpr] { ... } +# 368| getClosureBody(): [ExplicitClosureExpr] { ... } # 368| getBody(): [BraceStmt] { ... } # 369| getElement(0): [ReturnStmt] return ... # 369| getResult(): [DeclRefExpr] z # 369| getCapture(0): [CapturedDecl] z # 368| [ConcreteVarDecl] z # 368| Type = Int -# 373| [ConcreteFuncDecl] testTupleElement(t:) +# 373| [NamedFunction] testTupleElement(t:) # 373| InterfaceType = ((a: Int, Int, c: Int)) -> Int # 373| getParam(0): [ParamDecl] t # 373| Type = (a: Int, Int, c: Int) @@ -2461,20 +2461,20 @@ cfg.swift: # 374| getElement(1): [IntegerLiteralExpr] 2 # 374| getElement(2): [IntegerLiteralExpr] 3 # 377| [ClassDecl] Derived -# 378| getMember(0): [ConstructorDecl] Derived.init() +# 378| getMember(0): [Initializer] Derived.init() # 378| InterfaceType = (Derived.Type) -> () -> Derived # 378| getSelfParam(): [ParamDecl] self # 378| Type = Derived # 378| getBody(): [BraceStmt] { ... } -# 379| getElement(0): [RebindSelfInConstructorExpr] self = ... +# 379| getElement(0): [RebindSelfInInitializerExpr] self = ... # 379| getSubExpr(): [CallExpr] call to C.init(n:) # 379| getFunction(): [MethodLookupExpr] C.init(n:) # 379| getBase(): [SuperRefExpr] super -# 379| getMethodRef(): [OtherConstructorDeclRefExpr] C.init(n:) +# 379| getMethodRef(): [OtherInitializerRefExpr] C.init(n:) # 379| getArgument(0): [Argument] n: 0 # 379| getExpr(): [IntegerLiteralExpr] 0 # 380| getElement(1): [ReturnStmt] return -# 377| getMember(1): [ConstructorDecl] Derived.init(n:) +# 377| getMember(1): [Initializer] Derived.init(n:) # 377| InterfaceType = (Derived.Type) -> (Int) -> Derived # 377| getSelfParam(): [ParamDecl] self # 377| Type = Derived @@ -2494,12 +2494,12 @@ cfg.swift: # 377| getArgument(4): [Argument] : #... # 377| getExpr(): [MagicIdentifierLiteralExpr] #... #-----| getElement(1): [ReturnStmt] return -# 377| getMember(2): [DestructorDecl] Derived.deinit() +# 377| getMember(2): [Deinitializer] Derived.deinit() # 377| InterfaceType = (Derived) -> () -> () # 377| getSelfParam(): [ParamDecl] self # 377| Type = Derived # 377| getBody(): [BraceStmt] { ... } -# 383| [ConcreteFuncDecl] doWithoutCatch(x:) +# 383| [NamedFunction] doWithoutCatch(x:) # 383| InterfaceType = (Int) throws -> Int # 383| getParam(0): [ParamDecl] x # 383| Type = Int @@ -2547,7 +2547,7 @@ cfg.swift: # 394| getTypeRepr(): [TypeRepr] Int # 394| getMember(1): [ConcreteVarDecl] field # 394| Type = Int -# 394| getAccessorDecl(0): [AccessorDecl] get +# 394| getAccessor(0): [Accessor] get # 394| InterfaceType = (Structors) -> () -> Int # 394| getSelfParam(): [ParamDecl] self # 394| Type = Structors @@ -2555,7 +2555,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self -# 394| getAccessorDecl(1): [AccessorDecl] set +# 394| getAccessor(1): [Accessor] set # 394| InterfaceType = (Structors) -> (Int) -> () # 394| getSelfParam(): [ParamDecl] self # 394| Type = Structors @@ -2566,7 +2566,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 394| getAccessorDecl(2): [AccessorDecl] _modify +# 394| getAccessor(2): [Accessor] _modify # 394| InterfaceType = (Structors) -> () -> () # 394| getSelfParam(): [ParamDecl] self # 394| Type = Structors @@ -2575,7 +2575,7 @@ cfg.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self -# 395| getMember(2): [ConstructorDecl] Structors.init() +# 395| getMember(2): [Initializer] Structors.init() # 395| InterfaceType = (Structors.Type) -> () -> Structors # 395| getSelfParam(): [ParamDecl] self # 395| Type = Structors @@ -2585,7 +2585,7 @@ cfg.swift: # 396| getBase(): [DeclRefExpr] self # 396| getSource(): [IntegerLiteralExpr] 10 # 397| getElement(1): [ReturnStmt] return -# 399| getMember(3): [DestructorDecl] Structors.deinit() +# 399| getMember(3): [Deinitializer] Structors.deinit() # 399| InterfaceType = (Structors) -> () -> () # 399| getSelfParam(): [ParamDecl] self # 399| Type = Structors @@ -2594,7 +2594,7 @@ cfg.swift: # 400| getDest(): [MemberRefExpr] .field # 400| getBase(): [DeclRefExpr] self # 400| getSource(): [IntegerLiteralExpr] 0 -# 404| [ConcreteFuncDecl] dictionaryLiteral(x:y:) +# 404| [NamedFunction] dictionaryLiteral(x:y:) # 404| InterfaceType = (Int, Int) -> [String : Int] # 404| getParam(0): [ParamDecl] x # 404| Type = Int @@ -2609,7 +2609,7 @@ cfg.swift: # 405| getElement(1): [TupleExpr] (...) # 405| getElement(0): [StringLiteralExpr] y # 405| getElement(1): [DeclRefExpr] y -# 408| [ConcreteFuncDecl] localDeclarations() +# 408| [NamedFunction] localDeclarations() # 408| InterfaceType = () -> Int # 408| getBody(): [BraceStmt] { ... } # 409| getElement(0): [ClassDecl] MyLocalClass @@ -2619,7 +2619,7 @@ cfg.swift: # 410| getTypeRepr(): [TypeRepr] Int # 410| getMember(1): [ConcreteVarDecl] x # 410| Type = Int -# 410| getAccessorDecl(0): [AccessorDecl] get +# 410| getAccessor(0): [Accessor] get # 410| InterfaceType = (MyLocalClass) -> () -> Int # 410| getSelfParam(): [ParamDecl] self # 410| Type = MyLocalClass @@ -2627,7 +2627,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 410| getAccessorDecl(1): [AccessorDecl] set +# 410| getAccessor(1): [Accessor] set # 410| InterfaceType = (MyLocalClass) -> (Int) -> () # 410| getSelfParam(): [ParamDecl] self # 410| Type = MyLocalClass @@ -2638,7 +2638,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 410| getAccessorDecl(2): [AccessorDecl] _modify +# 410| getAccessor(2): [Accessor] _modify # 410| InterfaceType = (MyLocalClass) -> () -> () # 410| getSelfParam(): [ParamDecl] self # 410| Type = MyLocalClass @@ -2647,7 +2647,7 @@ cfg.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 411| getMember(2): [ConstructorDecl] MyLocalClass.init() +# 411| getMember(2): [Initializer] MyLocalClass.init() # 411| InterfaceType = (MyLocalClass.Type) -> () -> MyLocalClass # 411| getSelfParam(): [ParamDecl] self # 411| Type = MyLocalClass @@ -2657,7 +2657,7 @@ cfg.swift: # 412| getBase(): [DeclRefExpr] self # 412| getSource(): [IntegerLiteralExpr] 10 # 413| getElement(1): [ReturnStmt] return -# 409| getMember(3): [DestructorDecl] MyLocalClass.deinit() +# 409| getMember(3): [Deinitializer] MyLocalClass.deinit() # 409| InterfaceType = (MyLocalClass) -> () -> () # 409| getSelfParam(): [ParamDecl] self # 409| Type = MyLocalClass @@ -2669,7 +2669,7 @@ cfg.swift: # 417| getTypeRepr(): [TypeRepr] Int # 417| getMember(1): [ConcreteVarDecl] x # 417| Type = Int -# 417| getAccessorDecl(0): [AccessorDecl] get +# 417| getAccessor(0): [Accessor] get # 417| InterfaceType = (MyLocalStruct) -> () -> Int # 417| getSelfParam(): [ParamDecl] self # 417| Type = MyLocalStruct @@ -2677,7 +2677,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 417| getAccessorDecl(1): [AccessorDecl] set +# 417| getAccessor(1): [Accessor] set # 417| InterfaceType = (inout MyLocalStruct) -> (Int) -> () # 417| getSelfParam(): [ParamDecl] self # 417| Type = MyLocalStruct @@ -2688,7 +2688,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 417| getAccessorDecl(2): [AccessorDecl] _modify +# 417| getAccessor(2): [Accessor] _modify # 417| InterfaceType = (inout MyLocalStruct) -> () -> () # 417| getSelfParam(): [ParamDecl] self # 417| Type = MyLocalStruct @@ -2697,7 +2697,7 @@ cfg.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 418| getMember(2): [ConstructorDecl] MyLocalStruct.init() +# 418| getMember(2): [Initializer] MyLocalStruct.init() # 418| InterfaceType = (MyLocalStruct.Type) -> () -> MyLocalStruct # 418| getSelfParam(): [ParamDecl] self # 418| Type = MyLocalStruct @@ -2712,7 +2712,7 @@ cfg.swift: # 424| getMember(1): [EnumElementDecl] A # 425| getMember(2): [EnumCaseDecl] case ... # 425| getMember(3): [EnumElementDecl] B -#-----| getMember(4): [ConcreteFuncDecl] __derived_enum_equals(_:_:) +#-----| getMember(4): [NamedFunction] __derived_enum_equals(_:_:) #-----| InterfaceType = (MyLocalEnum.Type) -> (MyLocalEnum, MyLocalEnum) -> Bool #-----| getSelfParam(): [ParamDecl] self #-----| Type = MyLocalEnum.Type @@ -2771,7 +2771,7 @@ cfg.swift: #-----| getMember(5): [PatternBindingDecl] var ... = ... #-----| getPattern(0): [TypedPattern] ... as ... #-----| getSubPattern(): [NamedPattern] hashValue -#-----| getMember(6): [ConcreteFuncDecl] hash(into:) +#-----| getMember(6): [NamedFunction] hash(into:) #-----| InterfaceType = (MyLocalEnum) -> (inout Hasher) -> () #-----| getSelfParam(): [ParamDecl] self #-----| Type = MyLocalEnum @@ -2804,7 +2804,7 @@ cfg.swift: #-----| getExpr(): [DeclRefExpr] discriminator #-----| getMember(7): [ConcreteVarDecl] hashValue #-----| Type = Int -#-----| getAccessorDecl(0): [AccessorDecl] get +#-----| getAccessor(0): [Accessor] get #-----| InterfaceType = (MyLocalEnum) -> () -> Int #-----| getSelfParam(): [ParamDecl] self #-----| Type = MyLocalEnum @@ -2849,7 +2849,7 @@ cfg.swift: # 446| getTypeRepr(): [TypeRepr] Int # 446| getMember(1): [ConcreteVarDecl] x # 446| Type = Int -# 446| getAccessorDecl(0): [AccessorDecl] get +# 446| getAccessor(0): [Accessor] get # 446| InterfaceType = (B) -> () -> Int # 446| getSelfParam(): [ParamDecl] self # 446| Type = B @@ -2857,7 +2857,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 446| getAccessorDecl(1): [AccessorDecl] set +# 446| getAccessor(1): [Accessor] set # 446| InterfaceType = (inout B) -> (Int) -> () # 446| getSelfParam(): [ParamDecl] self # 446| Type = B @@ -2868,7 +2868,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 446| getAccessorDecl(2): [AccessorDecl] _modify +# 446| getAccessor(2): [Accessor] _modify # 446| InterfaceType = (inout B) -> () -> () # 446| getSelfParam(): [ParamDecl] self # 446| Type = B @@ -2877,7 +2877,7 @@ cfg.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 445| getMember(2): [ConstructorDecl] B.init(x:) +# 445| getMember(2): [Initializer] B.init(x:) # 445| InterfaceType = (B.Type) -> (Int) -> B # 445| getSelfParam(): [ParamDecl] self # 445| Type = B @@ -2890,7 +2890,7 @@ cfg.swift: # 450| getTypeRepr(): [TypeRepr] B # 450| getMember(1): [ConcreteVarDecl] b # 450| Type = B -# 450| getAccessorDecl(0): [AccessorDecl] get +# 450| getAccessor(0): [Accessor] get # 450| InterfaceType = (A) -> () -> B # 450| getSelfParam(): [ParamDecl] self # 450| Type = A @@ -2898,7 +2898,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .b #-----| getBase(): [DeclRefExpr] self -# 450| getAccessorDecl(1): [AccessorDecl] set +# 450| getAccessor(1): [Accessor] set # 450| InterfaceType = (inout A) -> (B) -> () # 450| getSelfParam(): [ParamDecl] self # 450| Type = A @@ -2909,7 +2909,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .b #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 450| getAccessorDecl(2): [AccessorDecl] _modify +# 450| getAccessor(2): [Accessor] _modify # 450| InterfaceType = (inout A) -> () -> () # 450| getSelfParam(): [ParamDecl] self # 450| Type = A @@ -2924,7 +2924,7 @@ cfg.swift: # 451| getTypeRepr(): [TypeRepr] [B] # 451| getMember(3): [ConcreteVarDecl] bs # 451| Type = [B] -# 451| getAccessorDecl(0): [AccessorDecl] get +# 451| getAccessor(0): [Accessor] get # 451| InterfaceType = (A) -> () -> [B] # 451| getSelfParam(): [ParamDecl] self # 451| Type = A @@ -2932,7 +2932,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .bs #-----| getBase(): [DeclRefExpr] self -# 451| getAccessorDecl(1): [AccessorDecl] set +# 451| getAccessor(1): [Accessor] set # 451| InterfaceType = (inout A) -> ([B]) -> () # 451| getSelfParam(): [ParamDecl] self # 451| Type = A @@ -2943,7 +2943,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .bs #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 451| getAccessorDecl(2): [AccessorDecl] _modify +# 451| getAccessor(2): [Accessor] _modify # 451| InterfaceType = (inout A) -> () -> () # 451| getSelfParam(): [ParamDecl] self # 451| Type = A @@ -2959,7 +2959,7 @@ cfg.swift: # 452| getTypeRepr(): [TypeRepr] B? # 452| getMember(5): [ConcreteVarDecl] mayB # 452| Type = B? -# 452| getAccessorDecl(0): [AccessorDecl] get +# 452| getAccessor(0): [Accessor] get # 452| InterfaceType = (A) -> () -> B? # 452| getSelfParam(): [ParamDecl] self # 452| Type = A @@ -2967,7 +2967,7 @@ cfg.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self -# 452| getAccessorDecl(1): [AccessorDecl] set +# 452| getAccessor(1): [Accessor] set # 452| InterfaceType = (inout A) -> (B?) -> () # 452| getSelfParam(): [ParamDecl] self # 452| Type = A @@ -2978,7 +2978,7 @@ cfg.swift: #-----| getDest(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 452| getAccessorDecl(2): [AccessorDecl] _modify +# 452| getAccessor(2): [Accessor] _modify # 452| InterfaceType = (inout A) -> () -> () # 452| getSelfParam(): [ParamDecl] self # 452| Type = A @@ -2987,7 +2987,7 @@ cfg.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self -# 449| getMember(6): [ConstructorDecl] A.init(b:bs:mayB:) +# 449| getMember(6): [Initializer] A.init(b:bs:mayB:) # 449| InterfaceType = (A.Type) -> (B, [B], B?) -> A # 449| getSelfParam(): [ParamDecl] self # 449| Type = A @@ -2997,7 +2997,7 @@ cfg.swift: # 449| Type = [B] # 449| getParam(2): [ParamDecl] mayB # 449| Type = B? -# 455| [ConcreteFuncDecl] test(a:) +# 455| [NamedFunction] test(a:) # 455| InterfaceType = (A) -> () # 455| getParam(0): [ParamDecl] a # 455| Type = A @@ -3072,7 +3072,7 @@ cfg.swift: # 464| getPattern(0): [NamedPattern] apply_kpGet_mayB_x # 464| getElement(15): [ConcreteVarDecl] apply_kpGet_mayB_x # 464| Type = Int? -# 467| [ConcreteFuncDecl] testIfConfig() +# 467| [NamedFunction] testIfConfig() # 467| InterfaceType = () -> () # 467| getBody(): [BraceStmt] { ... } # 468| getElement(0): [IfConfigDecl] #if ... @@ -3085,7 +3085,7 @@ cfg.swift: # 489| getElement(7): [IntegerLiteralExpr] 11 # 490| getElement(8): [IntegerLiteralExpr] 12 # 493| getElement(9): [IntegerLiteralExpr] 13 -# 496| [ConcreteFuncDecl] testAvailable() +# 496| [NamedFunction] testAvailable() # 496| InterfaceType = () -> Int # 496| getBody(): [BraceStmt] { ... } # 497| getElement(0): [PatternBindingDecl] var ... = ... @@ -3193,7 +3193,7 @@ declarations.swift: # 2| getPattern(0): [NamedPattern] x # 2| getMember(1): [ConcreteVarDecl] x # 2| Type = Int -# 2| getAccessorDecl(0): [AccessorDecl] get +# 2| getAccessor(0): [Accessor] get # 2| InterfaceType = (Foo) -> () -> Int # 2| getSelfParam(): [ParamDecl] self # 2| Type = Foo @@ -3201,7 +3201,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 2| getAccessorDecl(1): [AccessorDecl] set +# 2| getAccessor(1): [Accessor] set # 2| InterfaceType = (inout Foo) -> (Int) -> () # 2| getSelfParam(): [ParamDecl] self # 2| Type = Foo @@ -3212,7 +3212,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 2| getAccessorDecl(2): [AccessorDecl] _modify +# 2| getAccessor(2): [Accessor] _modify # 2| InterfaceType = (inout Foo) -> () -> () # 2| getSelfParam(): [ParamDecl] self # 2| Type = Foo @@ -3227,7 +3227,7 @@ declarations.swift: # 3| getTypeRepr(): [TypeRepr] Int # 3| getMember(3): [ConcreteVarDecl] next # 3| Type = Int -# 4| getAccessorDecl(0): [AccessorDecl] get +# 4| getAccessor(0): [Accessor] get # 4| InterfaceType = (Foo) -> () -> Int # 4| getSelfParam(): [ParamDecl] self # 4| Type = Foo @@ -3243,7 +3243,7 @@ declarations.swift: # 4| getBase(): [DeclRefExpr] self # 4| getArgument(1): [Argument] : 1 # 4| getExpr(): [IntegerLiteralExpr] 1 -# 5| getAccessorDecl(1): [AccessorDecl] set +# 5| getAccessor(1): [Accessor] set # 5| InterfaceType = (inout Foo) -> (Int) -> () # 5| getSelfParam(): [ParamDecl] self # 5| Type = Foo @@ -3262,7 +3262,7 @@ declarations.swift: # 5| getExpr(): [DeclRefExpr] newValue # 5| getArgument(1): [Argument] : 1 # 5| getExpr(): [IntegerLiteralExpr] 1 -# 3| getAccessorDecl(2): [AccessorDecl] _modify +# 3| getAccessor(2): [Accessor] _modify # 3| InterfaceType = (inout Foo) -> () -> () # 3| getSelfParam(): [ParamDecl] self # 3| Type = Foo @@ -3271,13 +3271,13 @@ declarations.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .next #-----| getBase(): [DeclRefExpr] self -# 1| getMember(4): [ConstructorDecl] Foo.init() +# 1| getMember(4): [Initializer] Foo.init() # 1| InterfaceType = (Foo.Type) -> () -> Foo # 1| getSelfParam(): [ParamDecl] self # 1| Type = Foo # 1| getBody(): [BraceStmt] { ... } # 1| getElement(0): [ReturnStmt] return -# 1| getMember(5): [ConstructorDecl] Foo.init(x:) +# 1| getMember(5): [Initializer] Foo.init(x:) # 1| InterfaceType = (Foo.Type) -> (Int) -> Foo # 1| getSelfParam(): [ParamDecl] self # 1| Type = Foo @@ -3291,7 +3291,7 @@ declarations.swift: # 9| getTypeRepr(): [TypeRepr] Double # 9| getMember(1): [ConcreteVarDecl] x # 9| Type = Double -# 9| getAccessorDecl(0): [AccessorDecl] get +# 9| getAccessor(0): [Accessor] get # 9| InterfaceType = (Bar) -> () -> Double # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar @@ -3299,7 +3299,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 9| getAccessorDecl(1): [AccessorDecl] set +# 9| getAccessor(1): [Accessor] set # 9| InterfaceType = (Bar) -> (Double) -> () # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar @@ -3310,7 +3310,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 9| getAccessorDecl(2): [AccessorDecl] _modify +# 9| getAccessor(2): [Accessor] _modify # 9| InterfaceType = (Bar) -> () -> () # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar @@ -3319,12 +3319,12 @@ declarations.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 9| getMember(2): [DestructorDecl] Bar.deinit() +# 9| getMember(2): [Deinitializer] Bar.deinit() # 9| InterfaceType = (Bar) -> () -> () # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar # 9| getBody(): [BraceStmt] { ... } -# 9| getMember(3): [ConstructorDecl] Bar.init() +# 9| getMember(3): [Initializer] Bar.init() # 9| InterfaceType = (Bar.Type) -> () -> Bar # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar @@ -3338,7 +3338,7 @@ declarations.swift: # 13| getMember(4): [EnumElementDecl] value3 # 13| getMember(5): [EnumElementDecl] value4 # 13| getMember(6): [EnumElementDecl] value5 -#-----| getMember(7): [ConcreteFuncDecl] __derived_enum_equals(_:_:) +#-----| getMember(7): [NamedFunction] __derived_enum_equals(_:_:) #-----| InterfaceType = (EnumValues.Type) -> (EnumValues, EnumValues) -> Bool #-----| getSelfParam(): [ParamDecl] self #-----| Type = EnumValues.Type @@ -3439,7 +3439,7 @@ declarations.swift: #-----| getMember(8): [PatternBindingDecl] var ... = ... #-----| getPattern(0): [TypedPattern] ... as ... #-----| getSubPattern(): [NamedPattern] hashValue -#-----| getMember(9): [ConcreteFuncDecl] hash(into:) +#-----| getMember(9): [NamedFunction] hash(into:) #-----| InterfaceType = (EnumValues) -> (inout Hasher) -> () #-----| getSelfParam(): [ParamDecl] self #-----| Type = EnumValues @@ -3493,7 +3493,7 @@ declarations.swift: #-----| getExpr(): [DeclRefExpr] discriminator #-----| getMember(10): [ConcreteVarDecl] hashValue #-----| Type = Int -#-----| getAccessorDecl(0): [AccessorDecl] get +#-----| getAccessor(0): [Accessor] get #-----| InterfaceType = (EnumValues) -> () -> Int #-----| getSelfParam(): [ParamDecl] self #-----| Type = EnumValues @@ -3528,17 +3528,17 @@ declarations.swift: # 23| getTypeRepr(): [TypeRepr] Int # 23| getMember(1): [ConcreteVarDecl] mustBeSettable # 23| Type = Int -# 23| getAccessorDecl(0): [AccessorDecl] get +# 23| getAccessor(0): [Accessor] get # 23| InterfaceType = (Self) -> () -> Int # 23| getSelfParam(): [ParamDecl] self # 23| Type = Self -# 23| getAccessorDecl(1): [AccessorDecl] set +# 23| getAccessor(1): [Accessor] set # 23| InterfaceType = (inout Self) -> (Int) -> () # 23| getSelfParam(): [ParamDecl] self # 23| Type = Self # 23| getParam(0): [ParamDecl] newValue # 23| Type = Int -# 23| getAccessorDecl(2): [AccessorDecl] _modify +# 23| getAccessor(2): [Accessor] _modify # 23| InterfaceType = (inout Self) -> () -> () # 23| getSelfParam(): [ParamDecl] self # 23| Type = Self @@ -3548,15 +3548,15 @@ declarations.swift: # 24| getTypeRepr(): [TypeRepr] Int # 24| getMember(3): [ConcreteVarDecl] doesNotNeedToBeSettable # 24| Type = Int -# 24| getAccessorDecl(0): [AccessorDecl] get +# 24| getAccessor(0): [Accessor] get # 24| InterfaceType = (Self) -> () -> Int # 24| getSelfParam(): [ParamDecl] self # 24| Type = Self -# 25| getMember(4): [ConcreteFuncDecl] random() +# 25| getMember(4): [NamedFunction] random() # 25| InterfaceType = (Self) -> () -> Double # 25| getSelfParam(): [ParamDecl] self # 25| Type = Self -# 28| [ConcreteFuncDecl] a_function(a_parameter:) +# 28| [NamedFunction] a_function(a_parameter:) # 28| InterfaceType = (Int) -> () # 28| getParam(0): [ParamDecl] a_parameter # 28| Type = Int @@ -3576,12 +3576,12 @@ declarations.swift: # 31| getTypeRepr(): [TypeRepr] String # 31| [ConcreteVarDecl] a_property # 31| Type = String -# 32| getAccessorDecl(0): [AccessorDecl] get +# 32| getAccessor(0): [Accessor] get # 32| InterfaceType = () -> String # 32| getBody(): [BraceStmt] { ... } # 33| getElement(0): [ReturnStmt] return ... # 33| getResult(): [StringLiteralExpr] here -# 35| getAccessorDecl(1): [AccessorDecl] set +# 35| getAccessor(1): [Accessor] set # 35| InterfaceType = (String) -> () # 35| getParam(0): [ParamDecl] newValue # 35| Type = String @@ -3606,7 +3606,7 @@ declarations.swift: # 41| getTypeRepr(): [TypeRepr] Int # 41| getMember(1): [ConcreteVarDecl] field # 41| Type = Int -# 41| getAccessorDecl(0): [AccessorDecl] get +# 41| getAccessor(0): [Accessor] get # 41| InterfaceType = (Baz) -> () -> Int # 41| getSelfParam(): [ParamDecl] self # 41| Type = Baz @@ -3614,7 +3614,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self -# 41| getAccessorDecl(1): [AccessorDecl] set +# 41| getAccessor(1): [Accessor] set # 41| InterfaceType = (Baz) -> (Int) -> () # 41| getSelfParam(): [ParamDecl] self # 41| Type = Baz @@ -3625,7 +3625,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 41| getAccessorDecl(2): [AccessorDecl] _modify +# 41| getAccessor(2): [Accessor] _modify # 41| InterfaceType = (Baz) -> () -> () # 41| getSelfParam(): [ParamDecl] self # 41| Type = Baz @@ -3634,7 +3634,7 @@ declarations.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .field #-----| getBase(): [DeclRefExpr] self -# 42| getMember(2): [ConstructorDecl] Baz.init() +# 42| getMember(2): [Initializer] Baz.init() # 42| InterfaceType = (Baz.Type) -> () -> Baz # 42| getSelfParam(): [ParamDecl] self # 42| Type = Baz @@ -3644,7 +3644,7 @@ declarations.swift: # 43| getBase(): [DeclRefExpr] self # 43| getSource(): [IntegerLiteralExpr] 10 # 44| getElement(1): [ReturnStmt] return -# 46| getMember(3): [DestructorDecl] Baz.deinit() +# 46| getMember(3): [Deinitializer] Baz.deinit() # 46| InterfaceType = (Baz) -> () -> () # 46| getSelfParam(): [ParamDecl] self # 46| Type = Baz @@ -3653,7 +3653,7 @@ declarations.swift: # 47| getDest(): [MemberRefExpr] .field # 47| getBase(): [DeclRefExpr] self # 47| getSource(): [IntegerLiteralExpr] 0 -# 50| getMember(4): [ConcreteFuncDecl] +-(_:) +# 50| getMember(4): [NamedFunction] +-(_:) # 50| InterfaceType = (Baz.Type) -> (Baz) -> Baz # 50| getSelfParam(): [ParamDecl] self # 50| Type = Baz.Type @@ -3673,20 +3673,20 @@ declarations.swift: # 69| getTypeRepr(): [TypeRepr] Int # 69| getMember(1): [ConcreteVarDecl] wrappedValue # 69| Type = Int -# 70| getAccessorDecl(0): [AccessorDecl] get +# 70| getAccessor(0): [Accessor] get # 70| InterfaceType = (ZeroWrapper) -> () -> Int # 70| getSelfParam(): [ParamDecl] self # 70| Type = ZeroWrapper # 70| getBody(): [BraceStmt] { ... } # 71| getElement(0): [ReturnStmt] return ... # 71| getResult(): [IntegerLiteralExpr] 0 -# 68| getMember(2): [ConstructorDecl] ZeroWrapper.init() +# 68| getMember(2): [Initializer] ZeroWrapper.init() # 68| InterfaceType = (ZeroWrapper.Type) -> () -> ZeroWrapper # 68| getSelfParam(): [ParamDecl] self # 68| Type = ZeroWrapper # 68| getBody(): [BraceStmt] { ... } # 68| getElement(0): [ReturnStmt] return -# 76| [ConcreteFuncDecl] foo() +# 76| [NamedFunction] foo() # 76| InterfaceType = () -> Int # 76| getBody(): [BraceStmt] { ... } # 77| getElement(0): [PatternBindingDecl] var ... = ... @@ -3695,7 +3695,7 @@ declarations.swift: # 77| getTypeRepr(): [TypeRepr] Int # 77| getElement(1): [ConcreteVarDecl] x # 77| Type = Int -# 77| getAccessorDecl(0): [AccessorDecl] get +# 77| getAccessor(0): [Accessor] get # 77| InterfaceType = () -> Int # 77| getBody(): [BraceStmt] { ... } #-----| getElement(0): [ReturnStmt] return ... @@ -3721,21 +3721,21 @@ declarations.swift: # 82| getTypeRepr(): [TypeRepr] Int # 82| getMember(1): [ConcreteVarDecl] settableField # 82| Type = Int -# 83| getAccessorDecl(0): [AccessorDecl] set +# 83| getAccessor(0): [Accessor] set # 83| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 83| getSelfParam(): [ParamDecl] self # 83| Type = HasPropertyAndObserver # 83| getParam(0): [ParamDecl] newValue # 83| Type = Int # 83| getBody(): [BraceStmt] { ... } -# 84| getAccessorDecl(1): [AccessorDecl] get +# 84| getAccessor(1): [Accessor] get # 84| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 84| getSelfParam(): [ParamDecl] self # 84| Type = HasPropertyAndObserver # 84| getBody(): [BraceStmt] { ... } # 85| getElement(0): [ReturnStmt] return ... # 85| getResult(): [IntegerLiteralExpr] 0 -# 82| getAccessorDecl(2): [AccessorDecl] _modify +# 82| getAccessor(2): [Accessor] _modify # 82| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 82| getSelfParam(): [ParamDecl] self # 82| Type = HasPropertyAndObserver @@ -3750,7 +3750,7 @@ declarations.swift: # 91| getTypeRepr(): [TypeRepr] Int # 91| getMember(3): [ConcreteVarDecl] readOnlyField1 # 91| Type = Int -# 91| getAccessorDecl(0): [AccessorDecl] get +# 91| getAccessor(0): [Accessor] get # 91| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 91| getSelfParam(): [ParamDecl] self # 91| Type = HasPropertyAndObserver @@ -3763,7 +3763,7 @@ declarations.swift: # 96| getTypeRepr(): [TypeRepr] Int # 96| getMember(5): [ConcreteVarDecl] readOnlyField2 # 96| Type = Int -# 97| getAccessorDecl(0): [AccessorDecl] get +# 97| getAccessor(0): [Accessor] get # 97| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 97| getSelfParam(): [ParamDecl] self # 97| Type = HasPropertyAndObserver @@ -3776,7 +3776,7 @@ declarations.swift: # 102| getTypeRepr(): [TypeRepr] Int # 102| getMember(7): [ConcreteVarDecl] normalField # 102| Type = Int -# 102| getAccessorDecl(0): [AccessorDecl] get +# 102| getAccessor(0): [Accessor] get # 102| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 102| getSelfParam(): [ParamDecl] self # 102| Type = HasPropertyAndObserver @@ -3784,7 +3784,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self -# 102| getAccessorDecl(1): [AccessorDecl] set +# 102| getAccessor(1): [Accessor] set # 102| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 102| getSelfParam(): [ParamDecl] self # 102| Type = HasPropertyAndObserver @@ -3795,7 +3795,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 102| getAccessorDecl(2): [AccessorDecl] _modify +# 102| getAccessor(2): [Accessor] _modify # 102| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 102| getSelfParam(): [ParamDecl] self # 102| Type = HasPropertyAndObserver @@ -3805,7 +3805,7 @@ declarations.swift: #-----| getSubExpr(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self # 104| getMember(8): [SubscriptDecl] subscript ... -# 105| getAccessorDecl(0): [AccessorDecl] get +# 105| getAccessor(0): [Accessor] get # 105| InterfaceType = (HasPropertyAndObserver) -> (Int) -> Int # 105| getSelfParam(): [ParamDecl] self # 105| Type = HasPropertyAndObserver @@ -3814,7 +3814,7 @@ declarations.swift: # 105| getBody(): [BraceStmt] { ... } # 106| getElement(0): [ReturnStmt] return ... # 106| getResult(): [IntegerLiteralExpr] 0 -# 108| getAccessorDecl(1): [AccessorDecl] set +# 108| getAccessor(1): [Accessor] set # 108| InterfaceType = (inout HasPropertyAndObserver) -> (Int, Int) -> () # 108| getSelfParam(): [ParamDecl] self # 108| Type = HasPropertyAndObserver @@ -3823,7 +3823,7 @@ declarations.swift: # 104| getParam(1): [ParamDecl] x # 104| Type = Int # 108| getBody(): [BraceStmt] { ... } -# 104| getAccessorDecl(2): [AccessorDecl] _modify +# 104| getAccessor(2): [Accessor] _modify # 104| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 104| getSelfParam(): [ParamDecl] self # 104| Type = HasPropertyAndObserver @@ -3839,7 +3839,7 @@ declarations.swift: # 104| getParam(0): [ParamDecl] x # 104| Type = Int # 111| getMember(9): [SubscriptDecl] subscript ... -# 111| getAccessorDecl(0): [AccessorDecl] get +# 111| getAccessor(0): [Accessor] get # 111| InterfaceType = (HasPropertyAndObserver) -> (Int, Int) -> Int # 111| getSelfParam(): [ParamDecl] self # 111| Type = HasPropertyAndObserver @@ -3860,14 +3860,14 @@ declarations.swift: # 115| getTypeRepr(): [TypeRepr] Int # 115| getMember(11): [ConcreteVarDecl] hasWillSet1 # 115| Type = Int -# 116| getAccessorDecl(0): [AccessorDecl] willSet +# 116| getAccessor(0): [Accessor] willSet # 116| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 116| getSelfParam(): [ParamDecl] self # 116| Type = HasPropertyAndObserver # 116| getParam(0): [ParamDecl] newValue # 116| Type = Int # 116| getBody(): [BraceStmt] { ... } -# 115| getAccessorDecl(1): [AccessorDecl] get +# 115| getAccessor(1): [Accessor] get # 115| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 115| getSelfParam(): [ParamDecl] self # 115| Type = HasPropertyAndObserver @@ -3875,7 +3875,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .hasWillSet1 #-----| getBase(): [DeclRefExpr] self -# 115| getAccessorDecl(2): [AccessorDecl] set +# 115| getAccessor(2): [Accessor] set # 115| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 115| getSelfParam(): [ParamDecl] self # 115| Type = HasPropertyAndObserver @@ -3893,7 +3893,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .hasWillSet1 #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 115| getAccessorDecl(3): [AccessorDecl] _modify +# 115| getAccessor(3): [Accessor] _modify # 115| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 115| getSelfParam(): [ParamDecl] self # 115| Type = HasPropertyAndObserver @@ -3908,14 +3908,14 @@ declarations.swift: # 119| getTypeRepr(): [TypeRepr] Int # 119| getMember(13): [ConcreteVarDecl] hasWillSet2 # 119| Type = Int -# 120| getAccessorDecl(0): [AccessorDecl] willSet +# 120| getAccessor(0): [Accessor] willSet # 120| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 120| getSelfParam(): [ParamDecl] self # 120| Type = HasPropertyAndObserver # 120| getParam(0): [ParamDecl] newValue # 120| Type = Int # 120| getBody(): [BraceStmt] { ... } -# 119| getAccessorDecl(1): [AccessorDecl] get +# 119| getAccessor(1): [Accessor] get # 119| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 119| getSelfParam(): [ParamDecl] self # 119| Type = HasPropertyAndObserver @@ -3923,7 +3923,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .hasWillSet2 #-----| getBase(): [DeclRefExpr] self -# 119| getAccessorDecl(2): [AccessorDecl] set +# 119| getAccessor(2): [Accessor] set # 119| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 119| getSelfParam(): [ParamDecl] self # 119| Type = HasPropertyAndObserver @@ -3941,7 +3941,7 @@ declarations.swift: #-----| getDest(): [MemberRefExpr] .hasWillSet2 #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 119| getAccessorDecl(3): [AccessorDecl] _modify +# 119| getAccessor(3): [Accessor] _modify # 119| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 119| getSelfParam(): [ParamDecl] self # 119| Type = HasPropertyAndObserver @@ -3956,14 +3956,14 @@ declarations.swift: # 123| getTypeRepr(): [TypeRepr] Int # 123| getMember(15): [ConcreteVarDecl] hasDidSet1 # 123| Type = Int -# 124| getAccessorDecl(0): [AccessorDecl] didSet +# 124| getAccessor(0): [Accessor] didSet # 124| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 124| getSelfParam(): [ParamDecl] self # 124| Type = HasPropertyAndObserver # 124| getParam(0): [ParamDecl] oldValue # 124| Type = Int # 124| getBody(): [BraceStmt] { ... } -# 123| getAccessorDecl(1): [AccessorDecl] get +# 123| getAccessor(1): [Accessor] get # 123| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 123| getSelfParam(): [ParamDecl] self # 123| Type = HasPropertyAndObserver @@ -3971,7 +3971,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .hasDidSet1 #-----| getBase(): [DeclRefExpr] self -# 123| getAccessorDecl(2): [AccessorDecl] set +# 123| getAccessor(2): [Accessor] set # 123| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 123| getSelfParam(): [ParamDecl] self # 123| Type = HasPropertyAndObserver @@ -3996,7 +3996,7 @@ declarations.swift: #-----| getMethodRef(): [DeclRefExpr] didSet #-----| getArgument(0): [Argument] : tmp #-----| getExpr(): [DeclRefExpr] tmp -# 123| getAccessorDecl(3): [AccessorDecl] _modify +# 123| getAccessor(3): [Accessor] _modify # 123| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 123| getSelfParam(): [ParamDecl] self # 123| Type = HasPropertyAndObserver @@ -4011,12 +4011,12 @@ declarations.swift: # 127| getTypeRepr(): [TypeRepr] Int # 127| getMember(17): [ConcreteVarDecl] hasDidSet2 # 127| Type = Int -# 128| getAccessorDecl(0): [AccessorDecl] didSet +# 128| getAccessor(0): [Accessor] didSet # 128| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 128| getSelfParam(): [ParamDecl] self # 128| Type = HasPropertyAndObserver # 128| getBody(): [BraceStmt] { ... } -# 127| getAccessorDecl(1): [AccessorDecl] get +# 127| getAccessor(1): [Accessor] get # 127| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 127| getSelfParam(): [ParamDecl] self # 127| Type = HasPropertyAndObserver @@ -4024,7 +4024,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .hasDidSet2 #-----| getBase(): [DeclRefExpr] self -# 127| getAccessorDecl(2): [AccessorDecl] set +# 127| getAccessor(2): [Accessor] set # 127| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 127| getSelfParam(): [ParamDecl] self # 127| Type = HasPropertyAndObserver @@ -4040,7 +4040,7 @@ declarations.swift: #-----| getBase(): [InOutExpr] &... #-----| getSubExpr(): [DeclRefExpr] self #-----| getMethodRef(): [DeclRefExpr] didSet -# 127| getAccessorDecl(3): [AccessorDecl] _modify +# 127| getAccessor(3): [Accessor] _modify # 127| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 127| getSelfParam(): [ParamDecl] self # 127| Type = HasPropertyAndObserver @@ -4060,19 +4060,19 @@ declarations.swift: # 131| getTypeRepr(): [TypeRepr] Int # 131| getMember(19): [ConcreteVarDecl] hasBoth # 131| Type = Int -# 132| getAccessorDecl(0): [AccessorDecl] willSet +# 132| getAccessor(0): [Accessor] willSet # 132| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 132| getSelfParam(): [ParamDecl] self # 132| Type = HasPropertyAndObserver # 132| getParam(0): [ParamDecl] newValue # 132| Type = Int # 132| getBody(): [BraceStmt] { ... } -# 134| getAccessorDecl(1): [AccessorDecl] didSet +# 134| getAccessor(1): [Accessor] didSet # 134| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 134| getSelfParam(): [ParamDecl] self # 134| Type = HasPropertyAndObserver # 134| getBody(): [BraceStmt] { ... } -# 131| getAccessorDecl(2): [AccessorDecl] get +# 131| getAccessor(2): [Accessor] get # 131| InterfaceType = (HasPropertyAndObserver) -> () -> Int # 131| getSelfParam(): [ParamDecl] self # 131| Type = HasPropertyAndObserver @@ -4080,7 +4080,7 @@ declarations.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .hasBoth #-----| getBase(): [DeclRefExpr] self -# 131| getAccessorDecl(3): [AccessorDecl] set +# 131| getAccessor(3): [Accessor] set # 131| InterfaceType = (inout HasPropertyAndObserver) -> (Int) -> () # 131| getSelfParam(): [ParamDecl] self # 131| Type = HasPropertyAndObserver @@ -4103,7 +4103,7 @@ declarations.swift: #-----| getBase(): [InOutExpr] &... #-----| getSubExpr(): [DeclRefExpr] self #-----| getMethodRef(): [DeclRefExpr] didSet -# 131| getAccessorDecl(4): [AccessorDecl] _modify +# 131| getAccessor(4): [Accessor] _modify # 131| InterfaceType = (inout HasPropertyAndObserver) -> () -> () # 131| getSelfParam(): [ParamDecl] self # 131| Type = HasPropertyAndObserver @@ -4112,7 +4112,7 @@ declarations.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .hasBoth #-----| getBase(): [DeclRefExpr] self -# 81| getMember(20): [ConstructorDecl] HasPropertyAndObserver.init(normalField:hasWillSet1:hasWillSet2:hasDidSet1:hasDidSet2:hasBoth:) +# 81| getMember(20): [Initializer] HasPropertyAndObserver.init(normalField:hasWillSet1:hasWillSet2:hasDidSet1:hasDidSet2:hasBoth:) # 81| InterfaceType = (HasPropertyAndObserver.Type) -> (Int, Int, Int, Int, Int, Int) -> HasPropertyAndObserver # 81| getSelfParam(): [ParamDecl] self # 81| Type = HasPropertyAndObserver @@ -4135,7 +4135,7 @@ declarations.swift: # 95| [Comment] // Or by adding an access declaration # 95| # 138| [ExtensionDecl] extension of Int -# 139| getMember(0): [ConcreteFuncDecl] id() +# 139| getMember(0): [NamedFunction] id() # 139| InterfaceType = (Int) -> () -> Int # 139| getSelfParam(): [ParamDecl] self # 139| Type = Int @@ -4152,7 +4152,7 @@ declarations.swift: # 146| getGenericTypeParam(0): [GenericTypeParamDecl] A # 146| getGenericTypeParam(1): [GenericTypeParamDecl] B # 146| getGenericTypeParam(2): [GenericTypeParamDecl] C -# 147| getMember(0): [ConcreteFuncDecl] genericMethod(_:_:_:) +# 147| getMember(0): [NamedFunction] genericMethod(_:_:_:) # 147| InterfaceType = (GenericClass) -> (A, B, C) -> () # 147| getSelfParam(): [ParamDecl] self # 147| Type = GenericClass @@ -4163,18 +4163,18 @@ declarations.swift: # 147| getParam(2): [ParamDecl] _ # 147| Type = C # 147| getBody(): [BraceStmt] { ... } -# 146| getMember(1): [DestructorDecl] GenericClass.deinit() +# 146| getMember(1): [Deinitializer] GenericClass.deinit() # 146| InterfaceType = (GenericClass) -> () -> () # 146| getSelfParam(): [ParamDecl] self # 146| Type = GenericClass # 146| getBody(): [BraceStmt] { ... } -# 146| getMember(2): [ConstructorDecl] GenericClass.init() +# 146| getMember(2): [Initializer] GenericClass.init() # 146| InterfaceType = (GenericClass.Type) -> () -> GenericClass # 146| getSelfParam(): [ParamDecl] self # 146| Type = GenericClass # 146| getBody(): [BraceStmt] { ... } # 146| getElement(0): [ReturnStmt] return -# 150| [ConcreteFuncDecl] genericFunc(_:_:_:) +# 150| [NamedFunction] genericFunc(_:_:_:) # 150| InterfaceType = (A, B, C) -> () # 150| getGenericTypeParam(0): [GenericTypeParamDecl] A # 150| getGenericTypeParam(1): [GenericTypeParamDecl] B @@ -4187,18 +4187,18 @@ declarations.swift: # 150| Type = C # 150| getBody(): [BraceStmt] { ... } # 152| [ClassDecl] Derived -# 152| getMember(0): [ConstructorDecl] Derived.init() +# 152| getMember(0): [Initializer] Derived.init() # 152| InterfaceType = (Derived.Type) -> () -> Derived # 152| getSelfParam(): [ParamDecl] self # 152| Type = Derived #-----| getBody(): [BraceStmt] { ... } -#-----| getElement(0): [RebindSelfInConstructorExpr] self = ... +#-----| getElement(0): [RebindSelfInInitializerExpr] self = ... #-----| getSubExpr(): [CallExpr] call to Baz.init() #-----| getFunction(): [MethodLookupExpr] Baz.init() #-----| getBase(): [SuperRefExpr] super -#-----| getMethodRef(): [OtherConstructorDeclRefExpr] Baz.init() +#-----| getMethodRef(): [OtherInitializerRefExpr] Baz.init() #-----| getElement(1): [ReturnStmt] return -# 152| getMember(1): [DestructorDecl] Derived.deinit() +# 152| getMember(1): [Deinitializer] Derived.deinit() # 152| InterfaceType = (Derived) -> () -> () # 152| getSelfParam(): [ParamDecl] self # 152| Type = Derived @@ -4221,7 +4221,7 @@ declarations.swift: # 155| getTypeRepr(): [TypeRepr] Baz? # 155| [ConcreteVarDecl] d # 155| Type = Baz? -# 157| [ConcreteFuncDecl] ifConfig() +# 157| [NamedFunction] ifConfig() # 157| InterfaceType = () -> () # 157| getBody(): [BraceStmt] { ... } # 158| getElement(0): [IfConfigDecl] #if ... @@ -4233,12 +4233,12 @@ declarations.swift: # 174| getElement(6): [IntegerLiteralExpr] 9 # 175| getElement(7): [IntegerLiteralExpr] 10 # 182| [ClassDecl] B -# 182| getMember(0): [DestructorDecl] B.deinit() +# 182| getMember(0): [Deinitializer] B.deinit() # 182| InterfaceType = (B) -> () -> () # 182| getSelfParam(): [ParamDecl] self # 182| Type = B # 182| getBody(): [BraceStmt] { ... } -# 182| getMember(1): [ConstructorDecl] B.init() +# 182| getMember(1): [Initializer] B.init() # 182| InterfaceType = (B.Type) -> () -> B # 182| getSelfParam(): [ParamDecl] self # 182| Type = B @@ -4336,7 +4336,7 @@ expressions.swift: # 10| [EnumDecl] AnError # 11| getMember(0): [EnumCaseDecl] case ... # 11| getMember(1): [EnumElementDecl] failed -#-----| getMember(2): [ConcreteFuncDecl] __derived_enum_equals(_:_:) +#-----| getMember(2): [NamedFunction] __derived_enum_equals(_:_:) #-----| InterfaceType = (AnError.Type) -> (AnError, AnError) -> Bool #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError.Type @@ -4381,7 +4381,7 @@ expressions.swift: #-----| getMember(3): [PatternBindingDecl] var ... = ... #-----| getPattern(0): [TypedPattern] ... as ... #-----| getSubPattern(): [NamedPattern] hashValue -#-----| getMember(4): [ConcreteFuncDecl] hash(into:) +#-----| getMember(4): [NamedFunction] hash(into:) #-----| InterfaceType = (AnError) -> (inout Hasher) -> () #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError @@ -4407,7 +4407,7 @@ expressions.swift: #-----| getExpr(): [DeclRefExpr] discriminator #-----| getMember(5): [ConcreteVarDecl] hashValue #-----| Type = Int -#-----| getAccessorDecl(0): [AccessorDecl] get +#-----| getAccessor(0): [Accessor] get #-----| InterfaceType = (AnError) -> () -> Int #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError @@ -4417,7 +4417,7 @@ expressions.swift: #-----| getFunction(): [DeclRefExpr] _hashValue(for:) #-----| getArgument(0): [Argument] for: self #-----| getExpr(): [DeclRefExpr] self -# 14| [ConcreteFuncDecl] failure(_:) +# 14| [NamedFunction] failure(_:) # 14| InterfaceType = (Int) throws -> () # 14| getParam(0): [ParamDecl] x # 14| Type = Int @@ -4457,13 +4457,13 @@ expressions.swift: # 21| getExpr(): [IntegerLiteralExpr] 11 # 21| getSubExpr().getFullyConverted(): [InjectIntoOptionalExpr] (()?) ... # 23| [ClassDecl] Klass -# 24| getMember(0): [ConstructorDecl] Klass.init() +# 24| getMember(0): [Initializer] Klass.init() # 24| InterfaceType = (Klass.Type) -> () -> Klass # 24| getSelfParam(): [ParamDecl] self # 24| Type = Klass # 24| getBody(): [BraceStmt] { ... } # 24| getElement(0): [ReturnStmt] return -# 23| getMember(1): [DestructorDecl] Klass.deinit() +# 23| getMember(1): [Deinitializer] Klass.deinit() # 23| InterfaceType = (Klass) -> () -> () # 23| getSelfParam(): [ParamDecl] self # 23| Type = Klass @@ -4534,7 +4534,7 @@ expressions.swift: # 35| getExpr(): [DefaultArgumentExpr] default separator # 35| getArgument(2): [Argument] terminator: default terminator # 35| getExpr(): [DefaultArgumentExpr] default terminator -# 37| [ConcreteFuncDecl] closured(closure:) +# 37| [NamedFunction] closured(closure:) # 37| InterfaceType = ((Int, Int) -> Int) -> () # 37| getParam(0): [ParamDecl] closure # 37| Type = (Int, Int) -> Int @@ -4550,7 +4550,7 @@ expressions.swift: # 41| getElement(0): [CallExpr] call to closured(closure:) # 41| getFunction(): [DeclRefExpr] closured(closure:) # 41| getArgument(0): [Argument] closure: { ... } -# 41| getExpr(): [ClosureExpr] { ... } +# 41| getExpr(): [ExplicitClosureExpr] { ... } # 41| getParam(0): [ParamDecl] x # 41| Type = Int # 41| getParam(1): [ParamDecl] y @@ -4571,7 +4571,7 @@ expressions.swift: # 44| getElement(0): [CallExpr] call to closured(closure:) # 44| getFunction(): [DeclRefExpr] closured(closure:) # 44| getArgument(0): [Argument] closure: { ... } -# 44| getExpr(): [ClosureExpr] { ... } +# 44| getExpr(): [ExplicitClosureExpr] { ... } # 44| getParam(0): [ParamDecl] x # 44| Type = Int # 44| getParam(1): [ParamDecl] y @@ -4592,7 +4592,7 @@ expressions.swift: # 47| getElement(0): [CallExpr] call to closured(closure:) # 47| getFunction(): [DeclRefExpr] closured(closure:) # 47| getArgument(0): [Argument] closure: { ... } -# 47| getExpr(): [ClosureExpr] { ... } +# 47| getExpr(): [ExplicitClosureExpr] { ... } # 47| getParam(0): [ParamDecl] $0 # 47| Type = Int # 47| getParam(1): [ParamDecl] $1 @@ -4613,7 +4613,7 @@ expressions.swift: # 48| getElement(0): [CallExpr] call to closured(closure:) # 48| getFunction(): [DeclRefExpr] closured(closure:) # 48| getArgument(0): [Argument] closure: { ... } -# 48| getExpr(): [ClosureExpr] { ... } +# 48| getExpr(): [ExplicitClosureExpr] { ... } # 48| getParam(0): [ParamDecl] $0 # 48| Type = Int # 48| getParam(1): [ParamDecl] $1 @@ -4636,7 +4636,7 @@ expressions.swift: # 51| getTypeRepr(): [TypeRepr] Int # 51| getMember(1): [ConcreteVarDecl] x # 51| Type = Int -# 51| getAccessorDecl(0): [AccessorDecl] get +# 51| getAccessor(0): [Accessor] get # 51| InterfaceType = (S) -> () -> Int # 51| getSelfParam(): [ParamDecl] self # 51| Type = S @@ -4644,7 +4644,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 50| getMember(2): [ConstructorDecl] S.init(x:) +# 50| getMember(2): [Initializer] S.init(x:) # 50| InterfaceType = (S.Type) -> (Int) -> S # 50| getSelfParam(): [ParamDecl] self # 50| Type = S @@ -4657,7 +4657,7 @@ expressions.swift: # 54| getSource(): [KeyPathExpr] #keyPath(...) # 54| getRoot(): [TypeRepr] S # 54| getComponent(0): [KeyPathComponent] KeyPathComponent -# 56| [ConcreteFuncDecl] unsafeFunction(pointer:) +# 56| [NamedFunction] unsafeFunction(pointer:) # 56| InterfaceType = (UnsafePointer) -> () # 56| getParam(0): [ParamDecl] pointer # 56| Type = UnsafePointer @@ -4685,7 +4685,7 @@ expressions.swift: # 60| getExpr(): [DeclRefExpr] myNumber # 60| getExpr().getFullyConverted(): [LoadExpr] (Int) ... # 60| getArgument(1): [Argument] : { ... } -# 60| getExpr(): [ClosureExpr] { ... } +# 60| getExpr(): [ExplicitClosureExpr] { ... } # 60| getParam(0): [ParamDecl] $0 # 60| Type = UnsafePointer # 60| getBody(): [BraceStmt] { ... } @@ -4696,7 +4696,7 @@ expressions.swift: # 60| getExpr(): [DeclRefExpr] $0 # 60| getExpr().getFullyConverted(): [FunctionConversionExpr] ((UnsafePointer) throws -> ()) ... # 62| [ClassDecl] FailingToInit -# 63| getMember(0): [ConstructorDecl] FailingToInit.init(x:) +# 63| getMember(0): [Initializer] FailingToInit.init(x:) # 63| InterfaceType = (FailingToInit.Type) -> (Int) -> FailingToInit? # 63| getSelfParam(): [ParamDecl] self # 63| Type = FailingToInit @@ -4718,7 +4718,7 @@ expressions.swift: # 64| getThen(): [BraceStmt] { ... } # 65| getElement(0): [FailStmt] fail # 67| getElement(1): [ReturnStmt] return -# 62| getMember(1): [DestructorDecl] FailingToInit.deinit() +# 62| getMember(1): [Deinitializer] FailingToInit.deinit() # 62| InterfaceType = (FailingToInit) -> () -> () # 62| getSelfParam(): [ParamDecl] self # 62| Type = FailingToInit @@ -4730,7 +4730,7 @@ expressions.swift: # 71| getTypeRepr(): [TypeRepr] Int # 71| getMember(1): [ConcreteVarDecl] xx # 71| Type = Int -# 71| getAccessorDecl(0): [AccessorDecl] get +# 71| getAccessor(0): [Accessor] get # 71| InterfaceType = (Base) -> () -> Int # 71| getSelfParam(): [ParamDecl] self # 71| Type = Base @@ -4738,7 +4738,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .xx #-----| getBase(): [DeclRefExpr] self -# 72| getMember(2): [ConstructorDecl] Base.init(x:) +# 72| getMember(2): [Initializer] Base.init(x:) # 72| InterfaceType = (Base.Type) -> (Int) -> Base # 72| getSelfParam(): [ParamDecl] self # 72| Type = Base @@ -4750,26 +4750,26 @@ expressions.swift: # 73| getBase(): [DeclRefExpr] self # 73| getSource(): [DeclRefExpr] x # 74| getElement(1): [ReturnStmt] return -# 70| getMember(3): [DestructorDecl] Base.deinit() +# 70| getMember(3): [Deinitializer] Base.deinit() # 70| InterfaceType = (Base) -> () -> () # 70| getSelfParam(): [ParamDecl] self # 70| Type = Base # 70| getBody(): [BraceStmt] { ... } # 77| [ClassDecl] Derived -# 78| getMember(0): [ConstructorDecl] Derived.init() +# 78| getMember(0): [Initializer] Derived.init() # 78| InterfaceType = (Derived.Type) -> () -> Derived # 78| getSelfParam(): [ParamDecl] self # 78| Type = Derived # 78| getBody(): [BraceStmt] { ... } -# 79| getElement(0): [RebindSelfInConstructorExpr] self = ... +# 79| getElement(0): [RebindSelfInInitializerExpr] self = ... # 79| getSubExpr(): [CallExpr] call to Base.init(x:) # 79| getFunction(): [MethodLookupExpr] Base.init(x:) # 79| getBase(): [SuperRefExpr] super -# 79| getMethodRef(): [OtherConstructorDeclRefExpr] Base.init(x:) +# 79| getMethodRef(): [OtherInitializerRefExpr] Base.init(x:) # 79| getArgument(0): [Argument] x: 22 # 79| getExpr(): [IntegerLiteralExpr] 22 # 80| getElement(1): [ReturnStmt] return -# 77| getMember(1): [ConstructorDecl] Derived.init(x:) +# 77| getMember(1): [Initializer] Derived.init(x:) # 77| InterfaceType = (Derived.Type) -> (Int) -> Derived # 77| getSelfParam(): [ParamDecl] self # 77| Type = Derived @@ -4789,7 +4789,7 @@ expressions.swift: # 77| getArgument(4): [Argument] : #... # 77| getExpr(): [MagicIdentifierLiteralExpr] #... #-----| getElement(1): [ReturnStmt] return -# 77| getMember(2): [DestructorDecl] Derived.deinit() +# 77| getMember(2): [Deinitializer] Derived.deinit() # 77| InterfaceType = (Derived) -> () -> () # 77| getSelfParam(): [ParamDecl] self # 77| Type = Derived @@ -4833,12 +4833,12 @@ expressions.swift: # 88| getArgument(0): [Argument] : a # 88| getExpr(): [StringLiteralExpr] a # 90| [ClassDecl] ToPtr -# 90| getMember(0): [DestructorDecl] ToPtr.deinit() +# 90| getMember(0): [Deinitializer] ToPtr.deinit() # 90| InterfaceType = (ToPtr) -> () -> () # 90| getSelfParam(): [ParamDecl] self # 90| Type = ToPtr # 90| getBody(): [BraceStmt] { ... } -# 90| getMember(1): [ConstructorDecl] ToPtr.init() +# 90| getMember(1): [Initializer] ToPtr.init() # 90| InterfaceType = (ToPtr.Type) -> () -> ToPtr # 90| getSelfParam(): [ParamDecl] self # 90| Type = ToPtr @@ -4881,21 +4881,21 @@ expressions.swift: # 96| getTypeRepr(): [TypeRepr] Int # 96| getMember(1): [ConcreteVarDecl] settableField # 96| Type = Int -# 97| getAccessorDecl(0): [AccessorDecl] set +# 97| getAccessor(0): [Accessor] set # 97| InterfaceType = (inout HasProperty) -> (Int) -> () # 97| getSelfParam(): [ParamDecl] self # 97| Type = HasProperty # 97| getParam(0): [ParamDecl] newValue # 97| Type = Int # 97| getBody(): [BraceStmt] { ... } -# 98| getAccessorDecl(1): [AccessorDecl] get +# 98| getAccessor(1): [Accessor] get # 98| InterfaceType = (HasProperty) -> () -> Int # 98| getSelfParam(): [ParamDecl] self # 98| Type = HasProperty # 98| getBody(): [BraceStmt] { ... } # 99| getElement(0): [ReturnStmt] return ... # 99| getResult(): [IntegerLiteralExpr] 0 -# 96| getAccessorDecl(2): [AccessorDecl] _modify +# 96| getAccessor(2): [Accessor] _modify # 96| InterfaceType = (inout HasProperty) -> () -> () # 96| getSelfParam(): [ParamDecl] self # 96| Type = HasProperty @@ -4910,7 +4910,7 @@ expressions.swift: # 105| getTypeRepr(): [TypeRepr] Int # 105| getMember(3): [ConcreteVarDecl] readOnlyField1 # 105| Type = Int -# 105| getAccessorDecl(0): [AccessorDecl] get +# 105| getAccessor(0): [Accessor] get # 105| InterfaceType = (HasProperty) -> () -> Int # 105| getSelfParam(): [ParamDecl] self # 105| Type = HasProperty @@ -4923,7 +4923,7 @@ expressions.swift: # 110| getTypeRepr(): [TypeRepr] Int # 110| getMember(5): [ConcreteVarDecl] readOnlyField2 # 110| Type = Int -# 111| getAccessorDecl(0): [AccessorDecl] get +# 111| getAccessor(0): [Accessor] get # 111| InterfaceType = (HasProperty) -> () -> Int # 111| getSelfParam(): [ParamDecl] self # 111| Type = HasProperty @@ -4936,7 +4936,7 @@ expressions.swift: # 116| getTypeRepr(): [TypeRepr] Int # 116| getMember(7): [ConcreteVarDecl] normalField # 116| Type = Int -# 116| getAccessorDecl(0): [AccessorDecl] get +# 116| getAccessor(0): [Accessor] get # 116| InterfaceType = (HasProperty) -> () -> Int # 116| getSelfParam(): [ParamDecl] self # 116| Type = HasProperty @@ -4944,7 +4944,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self -# 116| getAccessorDecl(1): [AccessorDecl] set +# 116| getAccessor(1): [Accessor] set # 116| InterfaceType = (inout HasProperty) -> (Int) -> () # 116| getSelfParam(): [ParamDecl] self # 116| Type = HasProperty @@ -4955,7 +4955,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 116| getAccessorDecl(2): [AccessorDecl] _modify +# 116| getAccessor(2): [Accessor] _modify # 116| InterfaceType = (inout HasProperty) -> () -> () # 116| getSelfParam(): [ParamDecl] self # 116| Type = HasProperty @@ -4965,7 +4965,7 @@ expressions.swift: #-----| getSubExpr(): [MemberRefExpr] .normalField #-----| getBase(): [DeclRefExpr] self # 118| getMember(8): [SubscriptDecl] subscript ... -# 119| getAccessorDecl(0): [AccessorDecl] get +# 119| getAccessor(0): [Accessor] get # 119| InterfaceType = (HasProperty) -> (Int) -> Int # 119| getSelfParam(): [ParamDecl] self # 119| Type = HasProperty @@ -4974,7 +4974,7 @@ expressions.swift: # 119| getBody(): [BraceStmt] { ... } # 120| getElement(0): [ReturnStmt] return ... # 120| getResult(): [IntegerLiteralExpr] 0 -# 122| getAccessorDecl(1): [AccessorDecl] set +# 122| getAccessor(1): [Accessor] set # 122| InterfaceType = (inout HasProperty) -> (Int, Int) -> () # 122| getSelfParam(): [ParamDecl] self # 122| Type = HasProperty @@ -4983,7 +4983,7 @@ expressions.swift: # 118| getParam(1): [ParamDecl] x # 118| Type = Int # 122| getBody(): [BraceStmt] { ... } -# 118| getAccessorDecl(2): [AccessorDecl] _modify +# 118| getAccessor(2): [Accessor] _modify # 118| InterfaceType = (inout HasProperty) -> (Int) -> () # 118| getSelfParam(): [ParamDecl] self # 118| Type = HasProperty @@ -4999,7 +4999,7 @@ expressions.swift: # 118| getParam(0): [ParamDecl] x # 118| Type = Int # 125| getMember(9): [SubscriptDecl] subscript ... -# 125| getAccessorDecl(0): [AccessorDecl] get +# 125| getAccessor(0): [Accessor] get # 125| InterfaceType = (HasProperty) -> (Int, Int) -> Int # 125| getSelfParam(): [ParamDecl] self # 125| Type = HasProperty @@ -5014,7 +5014,7 @@ expressions.swift: # 125| Type = Int # 125| getParam(1): [ParamDecl] y # 125| Type = Int -# 95| getMember(10): [ConstructorDecl] HasProperty.init(normalField:) +# 95| getMember(10): [Initializer] HasProperty.init(normalField:) # 95| InterfaceType = (HasProperty.Type) -> (Int) -> HasProperty # 95| getSelfParam(): [ParamDecl] self # 95| Type = HasProperty @@ -5026,7 +5026,7 @@ expressions.swift: # 104| # 109| [Comment] // Or by adding an access declaration # 109| -# 130| [ConcreteFuncDecl] testProperties(hp:) +# 130| [NamedFunction] testProperties(hp:) # 130| InterfaceType = (inout HasProperty) -> Int # 130| getParam(0): [ParamDecl] hp # 130| Type = HasProperty @@ -5089,7 +5089,7 @@ expressions.swift: # 142| getTypeRepr(): [TypeRepr] Int # 142| getMember(1): [ConcreteVarDecl] x # 142| Type = Int -# 142| getAccessorDecl(0): [AccessorDecl] get +# 142| getAccessor(0): [Accessor] get # 142| InterfaceType = (B) -> () -> Int # 142| getSelfParam(): [ParamDecl] self # 142| Type = B @@ -5097,7 +5097,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 142| getAccessorDecl(1): [AccessorDecl] set +# 142| getAccessor(1): [Accessor] set # 142| InterfaceType = (inout B) -> (Int) -> () # 142| getSelfParam(): [ParamDecl] self # 142| Type = B @@ -5108,7 +5108,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 142| getAccessorDecl(2): [AccessorDecl] _modify +# 142| getAccessor(2): [Accessor] _modify # 142| InterfaceType = (inout B) -> () -> () # 142| getSelfParam(): [ParamDecl] self # 142| Type = B @@ -5117,7 +5117,7 @@ expressions.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 141| getMember(2): [ConstructorDecl] B.init(x:) +# 141| getMember(2): [Initializer] B.init(x:) # 141| InterfaceType = (B.Type) -> (Int) -> B # 141| getSelfParam(): [ParamDecl] self # 141| Type = B @@ -5130,7 +5130,7 @@ expressions.swift: # 146| getTypeRepr(): [TypeRepr] B # 146| getMember(1): [ConcreteVarDecl] b # 146| Type = B -# 146| getAccessorDecl(0): [AccessorDecl] get +# 146| getAccessor(0): [Accessor] get # 146| InterfaceType = (A) -> () -> B # 146| getSelfParam(): [ParamDecl] self # 146| Type = A @@ -5138,7 +5138,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .b #-----| getBase(): [DeclRefExpr] self -# 146| getAccessorDecl(1): [AccessorDecl] set +# 146| getAccessor(1): [Accessor] set # 146| InterfaceType = (inout A) -> (B) -> () # 146| getSelfParam(): [ParamDecl] self # 146| Type = A @@ -5149,7 +5149,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .b #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 146| getAccessorDecl(2): [AccessorDecl] _modify +# 146| getAccessor(2): [Accessor] _modify # 146| InterfaceType = (inout A) -> () -> () # 146| getSelfParam(): [ParamDecl] self # 146| Type = A @@ -5164,7 +5164,7 @@ expressions.swift: # 147| getTypeRepr(): [TypeRepr] [B] # 147| getMember(3): [ConcreteVarDecl] bs # 147| Type = [B] -# 147| getAccessorDecl(0): [AccessorDecl] get +# 147| getAccessor(0): [Accessor] get # 147| InterfaceType = (A) -> () -> [B] # 147| getSelfParam(): [ParamDecl] self # 147| Type = A @@ -5172,7 +5172,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .bs #-----| getBase(): [DeclRefExpr] self -# 147| getAccessorDecl(1): [AccessorDecl] set +# 147| getAccessor(1): [Accessor] set # 147| InterfaceType = (inout A) -> ([B]) -> () # 147| getSelfParam(): [ParamDecl] self # 147| Type = A @@ -5183,7 +5183,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .bs #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 147| getAccessorDecl(2): [AccessorDecl] _modify +# 147| getAccessor(2): [Accessor] _modify # 147| InterfaceType = (inout A) -> () -> () # 147| getSelfParam(): [ParamDecl] self # 147| Type = A @@ -5199,7 +5199,7 @@ expressions.swift: # 148| getTypeRepr(): [TypeRepr] B? # 148| getMember(5): [ConcreteVarDecl] mayB # 148| Type = B? -# 148| getAccessorDecl(0): [AccessorDecl] get +# 148| getAccessor(0): [Accessor] get # 148| InterfaceType = (A) -> () -> B? # 148| getSelfParam(): [ParamDecl] self # 148| Type = A @@ -5207,7 +5207,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self -# 148| getAccessorDecl(1): [AccessorDecl] set +# 148| getAccessor(1): [Accessor] set # 148| InterfaceType = (inout A) -> (B?) -> () # 148| getSelfParam(): [ParamDecl] self # 148| Type = A @@ -5218,7 +5218,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 148| getAccessorDecl(2): [AccessorDecl] _modify +# 148| getAccessor(2): [Accessor] _modify # 148| InterfaceType = (inout A) -> () -> () # 148| getSelfParam(): [ParamDecl] self # 148| Type = A @@ -5227,7 +5227,7 @@ expressions.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .mayB #-----| getBase(): [DeclRefExpr] self -# 145| getMember(6): [ConstructorDecl] A.init(b:bs:mayB:) +# 145| getMember(6): [Initializer] A.init(b:bs:mayB:) # 145| InterfaceType = (A.Type) -> (B, [B], B?) -> A # 145| getSelfParam(): [ParamDecl] self # 145| Type = A @@ -5237,7 +5237,7 @@ expressions.swift: # 145| Type = [B] # 145| getParam(2): [ParamDecl] mayB # 145| Type = B? -# 151| [ConcreteFuncDecl] test(a:keyPathInt:keyPathB:) +# 151| [NamedFunction] test(a:keyPathInt:keyPathB:) # 151| InterfaceType = (A, WritableKeyPath, WritableKeyPath) -> () # 151| getParam(0): [ParamDecl] a # 151| Type = A @@ -5271,7 +5271,7 @@ expressions.swift: # 154| getPattern(0): [NamedPattern] nested_apply # 154| getElement(5): [ConcreteVarDecl] nested_apply # 154| Type = Int -# 157| [ConcreteFuncDecl] bitwise() +# 157| [NamedFunction] bitwise() # 157| InterfaceType = () -> () # 157| getBody(): [BraceStmt] { ... } # 158| getElement(0): [AssignExpr] ... = ... @@ -5345,7 +5345,7 @@ expressions.swift: # 167| getTypeRepr(): [TypeRepr] Int # 167| getMember(1): [ConcreteVarDecl] value # 167| Type = Int -# 167| getAccessorDecl(0): [AccessorDecl] get +# 167| getAccessor(0): [Accessor] get # 167| InterfaceType = (Bar) -> () -> Int # 167| getSelfParam(): [ParamDecl] self # 167| Type = Bar @@ -5353,7 +5353,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .value #-----| getBase(): [DeclRefExpr] self -# 167| getAccessorDecl(1): [AccessorDecl] set +# 167| getAccessor(1): [Accessor] set # 167| InterfaceType = (inout Bar) -> (Int) -> () # 167| getSelfParam(): [ParamDecl] self # 167| Type = Bar @@ -5364,7 +5364,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .value #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 167| getAccessorDecl(2): [AccessorDecl] _modify +# 167| getAccessor(2): [Accessor] _modify # 167| InterfaceType = (inout Bar) -> () -> () # 167| getSelfParam(): [ParamDecl] self # 167| Type = Bar @@ -5380,7 +5380,7 @@ expressions.swift: # 168| getTypeRepr(): [TypeRepr] Int? # 168| getMember(3): [ConcreteVarDecl] opt # 168| Type = Int? -# 168| getAccessorDecl(0): [AccessorDecl] get +# 168| getAccessor(0): [Accessor] get # 168| InterfaceType = (Bar) -> () -> Int? # 168| getSelfParam(): [ParamDecl] self # 168| Type = Bar @@ -5388,7 +5388,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self -# 168| getAccessorDecl(1): [AccessorDecl] set +# 168| getAccessor(1): [Accessor] set # 168| InterfaceType = (inout Bar) -> (Int?) -> () # 168| getSelfParam(): [ParamDecl] self # 168| Type = Bar @@ -5399,7 +5399,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 168| getAccessorDecl(2): [AccessorDecl] _modify +# 168| getAccessor(2): [Accessor] _modify # 168| InterfaceType = (inout Bar) -> () -> () # 168| getSelfParam(): [ParamDecl] self # 168| Type = Bar @@ -5408,7 +5408,7 @@ expressions.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self -# 166| getMember(4): [ConstructorDecl] Bar.init(value:opt:) +# 166| getMember(4): [Initializer] Bar.init(value:opt:) # 166| InterfaceType = (Bar.Type) -> (Int, Int?) -> Bar # 166| getSelfParam(): [ParamDecl] self # 166| Type = Bar @@ -5423,7 +5423,7 @@ expressions.swift: # 172| getTypeRepr(): [TypeRepr] Int # 172| getMember(1): [ConcreteVarDecl] value # 172| Type = Int -# 172| getAccessorDecl(0): [AccessorDecl] get +# 172| getAccessor(0): [Accessor] get # 172| InterfaceType = (Foo) -> () -> Int # 172| getSelfParam(): [ParamDecl] self # 172| Type = Foo @@ -5431,7 +5431,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .value #-----| getBase(): [DeclRefExpr] self -# 172| getAccessorDecl(1): [AccessorDecl] set +# 172| getAccessor(1): [Accessor] set # 172| InterfaceType = (inout Foo) -> (Int) -> () # 172| getSelfParam(): [ParamDecl] self # 172| Type = Foo @@ -5442,7 +5442,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .value #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 172| getAccessorDecl(2): [AccessorDecl] _modify +# 172| getAccessor(2): [Accessor] _modify # 172| InterfaceType = (inout Foo) -> () -> () # 172| getSelfParam(): [ParamDecl] self # 172| Type = Foo @@ -5458,7 +5458,7 @@ expressions.swift: # 173| getTypeRepr(): [TypeRepr] Bar? # 173| getMember(3): [ConcreteVarDecl] opt # 173| Type = Bar? -# 173| getAccessorDecl(0): [AccessorDecl] get +# 173| getAccessor(0): [Accessor] get # 173| InterfaceType = (Foo) -> () -> Bar? # 173| getSelfParam(): [ParamDecl] self # 173| Type = Foo @@ -5466,7 +5466,7 @@ expressions.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self -# 173| getAccessorDecl(1): [AccessorDecl] set +# 173| getAccessor(1): [Accessor] set # 173| InterfaceType = (inout Foo) -> (Bar?) -> () # 173| getSelfParam(): [ParamDecl] self # 173| Type = Foo @@ -5477,7 +5477,7 @@ expressions.swift: #-----| getDest(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 173| getAccessorDecl(2): [AccessorDecl] _modify +# 173| getAccessor(2): [Accessor] _modify # 173| InterfaceType = (inout Foo) -> () -> () # 173| getSelfParam(): [ParamDecl] self # 173| Type = Foo @@ -5486,7 +5486,7 @@ expressions.swift: #-----| getResult(0): [InOutExpr] &... #-----| getSubExpr(): [MemberRefExpr] .opt #-----| getBase(): [DeclRefExpr] self -# 171| getMember(4): [ConstructorDecl] Foo.init(value:opt:) +# 171| getMember(4): [Initializer] Foo.init(value:opt:) # 171| InterfaceType = (Foo.Type) -> (Int, Bar?) -> Foo # 171| getSelfParam(): [ParamDecl] self # 171| Type = Foo @@ -5577,7 +5577,7 @@ expressions.swift: # 183| [ConcreteVarDecl] tupleElement # 183| Type = WritableKeyPath<(Int, Int), Int> patterns.swift: -# 1| [ConcreteFuncDecl] basic_patterns() +# 1| [NamedFunction] basic_patterns() # 1| InterfaceType = () -> () # 1| getBody(): [BraceStmt] { ... } # 2| getElement(0): [PatternBindingDecl] var ... = ... @@ -5614,7 +5614,7 @@ patterns.swift: # 6| getInit(0): [StringLiteralExpr] paren # 6| getPattern(0): [AnyPattern] _ # 6| getPattern(0).getFullyUnresolved(): [ParenPattern] (...) -# 9| [ConcreteFuncDecl] switch_patterns() +# 9| [NamedFunction] switch_patterns() # 9| InterfaceType = () -> () # 9| getBody(): [BraceStmt] { ... } # 10| getElement(0): [PatternBindingDecl] var ... = ... @@ -5763,7 +5763,7 @@ patterns.swift: # 34| Type = Int # 42| [ConcreteVarDecl] x # 42| Type = String -# 54| [ConcreteFuncDecl] bound_and_unbound() +# 54| [NamedFunction] bound_and_unbound() # 54| InterfaceType = () -> () # 54| getBody(): [BraceStmt] { ... } # 55| getElement(0): [PatternBindingDecl] var ... = ... @@ -5852,12 +5852,12 @@ patterns.swift: # 58| Type = Int # 62| [ConcreteVarDecl] c # 62| Type = Int -# 67| [ConcreteFuncDecl] source() +# 67| [NamedFunction] source() # 67| InterfaceType = () -> Int # 67| getBody(): [BraceStmt] { ... } # 67| getElement(0): [ReturnStmt] return ... # 67| getResult(): [IntegerLiteralExpr] 0 -# 68| [ConcreteFuncDecl] sink(arg:) +# 68| [NamedFunction] sink(arg:) # 68| InterfaceType = (Int) -> () # 68| getParam(0): [ParamDecl] arg # 68| Type = Int @@ -5881,7 +5881,7 @@ patterns.swift: # 74| Type = Int # 74| getParam(1): [ParamDecl] _ # 74| Type = MyEnum -# 77| [ConcreteFuncDecl] test_enums() +# 77| [NamedFunction] test_enums() # 77| InterfaceType = () -> () # 77| getBody(): [BraceStmt] { ... } # 78| getElement(0): [PatternBindingDecl] var ... = ... @@ -6436,7 +6436,7 @@ patterns.swift: # 174| [ConcreteVarDecl] e # 174| Type = Int statements.swift: -# 1| [ConcreteFuncDecl] loop() +# 1| [NamedFunction] loop() # 1| InterfaceType = () -> () # 1| getBody(): [BraceStmt] { ... } # 2| getElement(0): [ForEachStmt] for ... in ... { ... } @@ -6598,7 +6598,7 @@ statements.swift: # 34| [EnumDecl] AnError # 35| getMember(0): [EnumCaseDecl] case ... # 35| getMember(1): [EnumElementDecl] failed -#-----| getMember(2): [ConcreteFuncDecl] __derived_enum_equals(_:_:) +#-----| getMember(2): [NamedFunction] __derived_enum_equals(_:_:) #-----| InterfaceType = (AnError.Type) -> (AnError, AnError) -> Bool #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError.Type @@ -6643,7 +6643,7 @@ statements.swift: #-----| getMember(3): [PatternBindingDecl] var ... = ... #-----| getPattern(0): [TypedPattern] ... as ... #-----| getSubPattern(): [NamedPattern] hashValue -#-----| getMember(4): [ConcreteFuncDecl] hash(into:) +#-----| getMember(4): [NamedFunction] hash(into:) #-----| InterfaceType = (AnError) -> (inout Hasher) -> () #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError @@ -6669,7 +6669,7 @@ statements.swift: #-----| getExpr(): [DeclRefExpr] discriminator #-----| getMember(5): [ConcreteVarDecl] hashValue #-----| Type = Int -#-----| getAccessorDecl(0): [AccessorDecl] get +#-----| getAccessor(0): [Accessor] get #-----| InterfaceType = (AnError) -> () -> Int #-----| getSelfParam(): [ParamDecl] self #-----| Type = AnError @@ -6679,7 +6679,7 @@ statements.swift: #-----| getFunction(): [DeclRefExpr] _hashValue(for:) #-----| getArgument(0): [Argument] for: self #-----| getExpr(): [DeclRefExpr] self -# 38| [ConcreteFuncDecl] failure(_:) +# 38| [NamedFunction] failure(_:) # 38| InterfaceType = (Int) throws -> () # 38| getParam(0): [ParamDecl] x # 38| Type = Int @@ -6868,7 +6868,7 @@ statements.swift: # 75| getTypeRepr(): [TypeRepr] Int # 75| getMember(1): [ConcreteVarDecl] x # 75| Type = Int -# 75| getAccessorDecl(0): [AccessorDecl] get +# 75| getAccessor(0): [Accessor] get # 75| InterfaceType = (HasModifyAccessorDecl) -> () -> Int # 75| getSelfParam(): [ParamDecl] self # 75| Type = HasModifyAccessorDecl @@ -6876,7 +6876,7 @@ statements.swift: #-----| getElement(0): [ReturnStmt] return ... #-----| getResult(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self -# 75| getAccessorDecl(1): [AccessorDecl] set +# 75| getAccessor(1): [Accessor] set # 75| InterfaceType = (inout HasModifyAccessorDecl) -> (Int) -> () # 75| getSelfParam(): [ParamDecl] self # 75| Type = HasModifyAccessorDecl @@ -6887,7 +6887,7 @@ statements.swift: #-----| getDest(): [MemberRefExpr] .x #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 75| getAccessorDecl(2): [AccessorDecl] _modify +# 75| getAccessor(2): [Accessor] _modify # 75| InterfaceType = (inout HasModifyAccessorDecl) -> () -> () # 75| getSelfParam(): [ParamDecl] self # 75| Type = HasModifyAccessorDecl @@ -6902,7 +6902,7 @@ statements.swift: # 76| getTypeRepr(): [TypeRepr] Int # 76| getMember(3): [ConcreteVarDecl] hasModify # 76| Type = Int -# 77| getAccessorDecl(0): [AccessorDecl] _modify +# 77| getAccessor(0): [Accessor] _modify # 77| InterfaceType = (inout HasModifyAccessorDecl) -> () -> () # 77| getSelfParam(): [ParamDecl] self # 77| Type = HasModifyAccessorDecl @@ -6911,14 +6911,14 @@ statements.swift: # 78| getResult(0): [InOutExpr] &... # 78| getSubExpr(): [MemberRefExpr] .x # 78| getBase(): [DeclRefExpr] self -# 81| getAccessorDecl(1): [AccessorDecl] get +# 81| getAccessor(1): [Accessor] get # 81| InterfaceType = (HasModifyAccessorDecl) -> () -> Int # 81| getSelfParam(): [ParamDecl] self # 81| Type = HasModifyAccessorDecl # 81| getBody(): [BraceStmt] { ... } # 82| getElement(0): [ReturnStmt] return ... # 82| getResult(): [IntegerLiteralExpr] 0 -# 76| getAccessorDecl(2): [AccessorDecl] set +# 76| getAccessor(2): [Accessor] set # 76| InterfaceType = (inout HasModifyAccessorDecl) -> (Int) -> () # 76| getSelfParam(): [ParamDecl] self # 76| Type = HasModifyAccessorDecl @@ -6929,7 +6929,7 @@ statements.swift: #-----| getDest(): [MemberRefExpr] .hasModify #-----| getBase(): [DeclRefExpr] self #-----| getSource(): [DeclRefExpr] value -# 74| getMember(4): [ConstructorDecl] HasModifyAccessorDecl.init(x:) +# 74| getMember(4): [Initializer] HasModifyAccessorDecl.init(x:) # 74| InterfaceType = (HasModifyAccessorDecl.Type) -> (Int) -> HasModifyAccessorDecl # 74| getSelfParam(): [ParamDecl] self # 74| Type = HasModifyAccessorDecl diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected deleted file mode 100644 index 49d4c192730..00000000000 --- a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected +++ /dev/null @@ -1,9 +0,0 @@ -| abstractfunctiondecl.swift:2:1:2:15 | func1() | getName:func1(), hasName:func1() | -| abstractfunctiondecl.swift:5:2:5:16 | func2() | MethodDecl, getName:func2(), hasName:func2(), hasQualifiedName(2):Class1.func2(), hasQualifiedName(3):abstractfunctiondecl.Class1.func2(), memberOf:Class1 | -| abstractfunctiondecl.swift:8:3:8:17 | func3() | MethodDecl, getName:func3(), hasName:func3(), hasQualifiedName(2):Class1.Class2.func3(), hasQualifiedName(3):abstractfunctiondecl.Class1.Class2.func3(), memberOf:Class1.Class2 | -| abstractfunctiondecl.swift:13:2:13:13 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Protocol1.func4(), hasQualifiedName(3):abstractfunctiondecl.Protocol1.func4(), memberOf:Protocol1 | -| abstractfunctiondecl.swift:17:2:17:16 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Class3.func4(), hasQualifiedName(3):abstractfunctiondecl.Class3.func4(), memberOf:Class3 | -| abstractfunctiondecl.swift:21:2:21:16 | func5() | MethodDecl, getName:func5(), hasName:func5(), hasQualifiedName(2):Class3.func5(), hasQualifiedName(3):abstractfunctiondecl.Class3.func5(), memberOf:Class3 | -| abstractfunctiondecl.swift:25:2:25:16 | func6() | MethodDecl, getName:func6(), hasName:func6(), hasQualifiedName(2):Struct1.func6(), hasQualifiedName(3):abstractfunctiondecl.Struct1.func6(), memberOf:Struct1 | -| abstractfunctiondecl.swift:31:2:31:16 | func7() | MethodDecl, getName:func7(), hasName:func7(), hasQualifiedName(2):Enum1.func7(), hasQualifiedName(3):abstractfunctiondecl.Enum1.func7(), memberOf:Enum1 | -| abstractfunctiondecl.swift:37:3:37:17 | func8() | MethodDecl, getName:func8(), hasName:func8(), hasQualifiedName(2):Class1.Class4.func8(), hasQualifiedName(3):abstractfunctiondecl.Class1.Class4.func8(), memberOf:Class1.Class4 | diff --git a/swift/ql/test/library-tests/elements/decl/function/function.expected b/swift/ql/test/library-tests/elements/decl/function/function.expected new file mode 100644 index 00000000000..462f2175f4e --- /dev/null +++ b/swift/ql/test/library-tests/elements/decl/function/function.expected @@ -0,0 +1,9 @@ +| function.swift:2:1:2:15 | func1() | getName:func1(), hasName:func1() | +| function.swift:5:2:5:16 | func2() | Method, getName:func2(), hasName:func2(), hasQualifiedName(2):Class1.func2(), hasQualifiedName(3):function.Class1.func2(), memberOf:Class1 | +| function.swift:8:3:8:17 | func3() | Method, getName:func3(), hasName:func3(), hasQualifiedName(2):Class1.Class2.func3(), hasQualifiedName(3):function.Class1.Class2.func3(), memberOf:Class1.Class2 | +| function.swift:13:2:13:13 | func4() | Method, getName:func4(), hasName:func4(), hasQualifiedName(2):Protocol1.func4(), hasQualifiedName(3):function.Protocol1.func4(), memberOf:Protocol1 | +| function.swift:17:2:17:16 | func4() | Method, getName:func4(), hasName:func4(), hasQualifiedName(2):Class3.func4(), hasQualifiedName(3):function.Class3.func4(), memberOf:Class3 | +| function.swift:21:2:21:16 | func5() | Method, getName:func5(), hasName:func5(), hasQualifiedName(2):Class3.func5(), hasQualifiedName(3):function.Class3.func5(), memberOf:Class3 | +| function.swift:25:2:25:16 | func6() | Method, getName:func6(), hasName:func6(), hasQualifiedName(2):Struct1.func6(), hasQualifiedName(3):function.Struct1.func6(), memberOf:Struct1 | +| function.swift:31:2:31:16 | func7() | Method, getName:func7(), hasName:func7(), hasQualifiedName(2):Enum1.func7(), hasQualifiedName(3):function.Enum1.func7(), memberOf:Enum1 | +| function.swift:37:3:37:17 | func8() | Method, getName:func8(), hasName:func8(), hasQualifiedName(2):Class1.Class4.func8(), hasQualifiedName(3):function.Class1.Class4.func8(), memberOf:Class1.Class4 | diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql b/swift/ql/test/library-tests/elements/decl/function/function.ql similarity index 72% rename from swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql rename to swift/ql/test/library-tests/elements/decl/function/function.ql index acd05cc4438..9468929d194 100644 --- a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql +++ b/swift/ql/test/library-tests/elements/decl/function/function.ql @@ -1,6 +1,6 @@ import swift -string describe(AbstractFunctionDecl f) { +string describe(Function f) { result = "getName:" + f.getName() or exists(string a | @@ -8,15 +8,15 @@ string describe(AbstractFunctionDecl f) { result = "hasName:" + a ) or - result = "MethodDecl" and f instanceof MethodDecl + result = "Method" and f instanceof Method or exists(string a, string b | - f.(MethodDecl).hasQualifiedName(a, b) and + f.(Method).hasQualifiedName(a, b) and result = "hasQualifiedName(2):" + a + "." + b ) or exists(string a, string b, string c | - f.(MethodDecl).hasQualifiedName(a, b, c) and + f.(Method).hasQualifiedName(a, b, c) and result = "hasQualifiedName(3):" + a + "." + b + "." + c ) or @@ -25,7 +25,7 @@ string describe(AbstractFunctionDecl f) { ) } -from AbstractFunctionDecl f +from Function f where not f.getFile() instanceof UnknownFile and not f.getName().matches("%init%") diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift b/swift/ql/test/library-tests/elements/decl/function/function.swift similarity index 100% rename from swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift rename to swift/ql/test/library-tests/elements/decl/function/function.swift diff --git a/swift/ql/test/library-tests/elements/expr/methodlookup/PrintAst.expected b/swift/ql/test/library-tests/elements/expr/methodlookup/PrintAst.expected index aa2eba69220..cbe03b39e9d 100644 --- a/swift/ql/test/library-tests/elements/expr/methodlookup/PrintAst.expected +++ b/swift/ql/test/library-tests/elements/expr/methodlookup/PrintAst.expected @@ -1,44 +1,44 @@ methodlookup.swift: # 1| [ClassDecl] Foo -# 2| getMember(0): [ConstructorDecl] Foo.init() +# 2| getMember(0): [Initializer] Foo.init() # 2| InterfaceType = (Foo.Type) -> () -> Foo # 2| getSelfParam(): [ParamDecl] self # 2| Type = Foo # 2| getBody(): [BraceStmt] { ... } # 2| getElement(0): [ReturnStmt] return -# 3| getMember(1): [ConcreteFuncDecl] instanceMethod() +# 3| getMember(1): [NamedFunction] instanceMethod() # 3| InterfaceType = (Foo) -> () -> () # 3| getSelfParam(): [ParamDecl] self # 3| Type = Foo # 3| getBody(): [BraceStmt] { ... } -# 4| getMember(2): [ConcreteFuncDecl] staticMethod() +# 4| getMember(2): [NamedFunction] staticMethod() # 4| InterfaceType = (Foo.Type) -> () -> () # 4| getSelfParam(): [ParamDecl] self # 4| Type = Foo.Type # 4| getBody(): [BraceStmt] { ... } -# 5| getMember(3): [ConcreteFuncDecl] classMethod() +# 5| getMember(3): [NamedFunction] classMethod() # 5| InterfaceType = (Foo.Type) -> () -> () # 5| getSelfParam(): [ParamDecl] self # 5| Type = Foo.Type # 5| getBody(): [BraceStmt] { ... } -# 1| getMember(4): [DestructorDecl] Foo.deinit() +# 1| getMember(4): [Deinitializer] Foo.deinit() # 1| InterfaceType = (Foo) -> () -> () # 1| getSelfParam(): [ParamDecl] self # 1| Type = Foo # 1| getBody(): [BraceStmt] { ... } # 8| [ClassDecl] Bar -# 9| getMember(0): [ConstructorDecl] Bar.init() +# 9| getMember(0): [Initializer] Bar.init() # 9| InterfaceType = (Bar.Type) -> () -> Bar # 9| getSelfParam(): [ParamDecl] self # 9| Type = Bar # 9| getBody(): [BraceStmt] { ... } # 9| getElement(0): [ReturnStmt] return -# 10| getMember(1): [ConcreteFuncDecl] instanceMethod() +# 10| getMember(1): [NamedFunction] instanceMethod() # 10| InterfaceType = (isolated Bar) -> () -> () # 10| getSelfParam(): [ParamDecl] self # 10| Type = Bar # 10| getBody(): [BraceStmt] { ... } -# 11| getMember(2): [ConcreteFuncDecl] staticMethod() +# 11| getMember(2): [NamedFunction] staticMethod() # 11| InterfaceType = (Bar.Type) -> () -> () # 11| getSelfParam(): [ParamDecl] self # 11| Type = Bar.Type @@ -46,14 +46,14 @@ methodlookup.swift: #-----| getMember(3): [PatternBindingDecl] var ... = ... #-----| getPattern(0): [TypedPattern] ... as ... #-----| getSubPattern(): [NamedPattern] unownedExecutor -# 8| getMember(4): [DestructorDecl] Bar.deinit() +# 8| getMember(4): [Deinitializer] Bar.deinit() # 8| InterfaceType = (Bar) -> () -> () # 8| getSelfParam(): [ParamDecl] self # 8| Type = Bar # 8| getBody(): [BraceStmt] { ... } #-----| getMember(5): [ConcreteVarDecl] unownedExecutor #-----| Type = UnownedSerialExecutor -#-----| getAccessorDecl(0): [AccessorDecl] get +#-----| getAccessor(0): [Accessor] get #-----| InterfaceType = (Bar) -> () -> UnownedSerialExecutor #-----| getSelfParam(): [ParamDecl] self #-----| Type = Bar @@ -69,28 +69,28 @@ methodlookup.swift: #-----| getArgument(0): [Argument] : self #-----| getExpr(): [DeclRefExpr] self # 15| [ClassDecl] Baz -# 16| getMember(0): [ConstructorDecl] Baz.init() +# 16| getMember(0): [Initializer] Baz.init() # 16| InterfaceType = (Baz.Type) -> () -> Baz # 16| getSelfParam(): [ParamDecl] self # 16| Type = Baz # 16| getBody(): [BraceStmt] { ... } # 16| getElement(0): [ReturnStmt] return -# 17| getMember(1): [ConcreteFuncDecl] instanceMethod() +# 17| getMember(1): [NamedFunction] instanceMethod() # 17| InterfaceType = (Baz) -> () -> () # 17| getSelfParam(): [ParamDecl] self # 17| Type = Baz # 17| getBody(): [BraceStmt] { ... } -# 18| getMember(2): [ConcreteFuncDecl] staticMethod() +# 18| getMember(2): [NamedFunction] staticMethod() # 18| InterfaceType = (Baz.Type) -> () -> () # 18| getSelfParam(): [ParamDecl] self # 18| Type = Baz.Type # 18| getBody(): [BraceStmt] { ... } -# 19| getMember(3): [ConcreteFuncDecl] classMethod() +# 19| getMember(3): [NamedFunction] classMethod() # 19| InterfaceType = (Baz.Type) -> () -> () # 19| getSelfParam(): [ParamDecl] self # 19| Type = Baz.Type # 19| getBody(): [BraceStmt] { ... } -# 15| getMember(4): [DestructorDecl] Baz.deinit() +# 15| getMember(4): [Deinitializer] Baz.deinit() # 15| InterfaceType = (Baz) -> () -> () # 15| getSelfParam(): [ParamDecl] self # 15| Type = Baz @@ -159,7 +159,7 @@ methodlookup.swift: # 33| getArgument(0): [Argument] priority: default priority # 33| getExpr(): [DefaultArgumentExpr] default priority # 33| getArgument(1): [Argument] operation: { ... } -# 33| getExpr(): [ClosureExpr] { ... } +# 33| getExpr(): [ExplicitClosureExpr] { ... } # 33| getBody(): [BraceStmt] { ... } # 34| getElement(0): [PatternBindingDecl] var ... = ... # 34| getInit(0): [CallExpr] call to Bar.init() @@ -200,7 +200,7 @@ methodlookup.swift: # 43| getArgument(0): [Argument] priority: default priority # 43| getExpr(): [DefaultArgumentExpr] default priority # 43| getArgument(1): [Argument] operation: { ... } -# 43| getExpr(): [ClosureExpr] { ... } +# 43| getExpr(): [ExplicitClosureExpr] { ... } # 43| getBody(): [BraceStmt] { ... } # 44| getElement(0): [PatternBindingDecl] var ... = ... # 44| getInit(0): [CallExpr] call to Baz.init() From 16fc42a53f671f93877bc8b81a5f468ee6b3852c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 16:01:57 +0200 Subject: [PATCH 37/96] Swift: fix formatting --- .../swift/controlflow/internal/ControlFlowElements.qll | 4 +--- swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll | 4 +--- .../dataflow/internal/FlowSummaryImplSpecific.qll | 4 +--- .../codeql/swift/security/UnsafeJsEvalExtensions.qll | 10 ++++------ .../swift/security/UnsafeWebViewFetchExtensions.qll | 4 +--- swift/ql/test/TestUtils.qll | 1 - 6 files changed, 8 insertions(+), 19 deletions(-) diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll index d01f60a1cd1..b98adf4dde8 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll @@ -69,9 +69,7 @@ private predicate isPropertySetterElement(Accessor accessor, AssignExpr assign) ) } -predicate isPropertySetterElement( - PropertySetterElement pse, Accessor accessor, AssignExpr assign -) { +predicate isPropertySetterElement(PropertySetterElement pse, Accessor accessor, AssignExpr assign) { pse = TPropertySetterElement(accessor, assign) } diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index eac0cbb1c1a..7193d8c4f5f 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -397,9 +397,7 @@ private string paramsStringPart(Function c, int i) { * Parameter types are represented by their type erasure. */ cached -string paramsString(Function c) { - result = concat(int i | | paramsStringPart(c, i) order by i) -} +string paramsString(Function c) { result = concat(int i | | paramsStringPart(c, i) order by i) } bindingset[func] predicate matchesSignature(Function func, string signature) { diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll index f04b2916014..1d6d5631fec 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll @@ -58,9 +58,7 @@ DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { any( * Holds if an external flow summary exists for `c` with input specification * `input`, output specification `output`, kind `kind`, and provenance `provenance`. */ -predicate summaryElement( - Function c, string input, string output, string kind, string provenance -) { +predicate summaryElement(Function c, string input, string output, string kind, string provenance) { exists( string namespace, string type, boolean subtypes, string name, string signature, string ext | diff --git a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll index 32d49253074..5bf57371c0d 100644 --- a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalExtensions.qll @@ -51,9 +51,7 @@ private class WKWebViewDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { private class WKUserContentControllerDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { WKUserContentControllerDefaultUnsafeJsEvalSink() { any(CallExpr ce | - ce.getStaticTarget() - .(Method) - .hasQualifiedName("WKUserContentController", "addUserScript(_:)") + ce.getStaticTarget().(Method).hasQualifiedName("WKUserContentController", "addUserScript(_:)") ).getArgument(0).getExpr() = this.asExpr() } } @@ -89,9 +87,9 @@ private class JSContextDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { */ private class JSEvaluateScriptDefaultUnsafeJsEvalSink extends UnsafeJsEvalSink { JSEvaluateScriptDefaultUnsafeJsEvalSink() { - any(CallExpr ce | - ce.getStaticTarget().(FreeFunction).hasName("JSEvaluateScript(_:_:_:_:_:_:)") - ).getArgument(1).getExpr() = this.asExpr() + any(CallExpr ce | ce.getStaticTarget().(FreeFunction).hasName("JSEvaluateScript(_:_:_:_:_:_:)")) + .getArgument(1) + .getExpr() = this.asExpr() } } diff --git a/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll b/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll index d0d2cda8864..b8264fd5511 100644 --- a/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/UnsafeWebViewFetchExtensions.qll @@ -38,9 +38,7 @@ private class UIKitWebKitWebViewFetchSink extends UnsafeWebViewFetchSink { Expr baseUrl; UIKitWebKitWebViewFetchSink() { - exists( - Method funcDecl, CallExpr call, string className, string funcName, int arg, int baseArg - | + exists(Method funcDecl, CallExpr call, string className, string funcName, int arg, int baseArg | // arguments to method calls... ( // `loadHTMLString` diff --git a/swift/ql/test/TestUtils.qll b/swift/ql/test/TestUtils.qll index bc8e991b756..40bf78d96b6 100644 --- a/swift/ql/test/TestUtils.qll +++ b/swift/ql/test/TestUtils.qll @@ -1,6 +1,5 @@ private import codeql.swift.elements private import codeql.swift.generated.ParentChild - // Internal classes are not imported by the tests: import codeql.swift.elements.expr.InitializerRefCallExpr import codeql.swift.elements.expr.DotSyntaxCallExpr From 6f804ff1e7ee4dfe3a60ee5dadc5b5f5435ee64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 26 Apr 2023 17:03:20 +0200 Subject: [PATCH 38/96] Swift: upgrade/downgrade scripts --- .../old.dbscheme | 2630 +++++++++++++++++ .../swift.dbscheme | 2630 +++++++++++++++++ .../upgrade.properties | 56 + .../old.dbscheme | 2630 +++++++++++++++++ .../swift.dbscheme | 2630 +++++++++++++++++ .../upgrade.properties | 56 + 6 files changed, 10632 insertions(+) create mode 100644 swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/old.dbscheme create mode 100644 swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/swift.dbscheme create mode 100644 swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/upgrade.properties create mode 100644 swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/old.dbscheme create mode 100644 swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/swift.dbscheme create mode 100644 swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/upgrade.properties diff --git a/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/old.dbscheme b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/old.dbscheme new file mode 100644 index 00000000000..ba4171b90d0 --- /dev/null +++ b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/old.dbscheme @@ -0,0 +1,2630 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @explicit_closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@explicit_closure_expr_or_none = + @explicit_closure_expr +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/swift.dbscheme b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/swift.dbscheme new file mode 100644 index 00000000000..f937d9e6309 --- /dev/null +++ b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/swift.dbscheme @@ -0,0 +1,2630 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/upgrade.properties b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/upgrade.properties new file mode 100644 index 00000000000..f1bfc92ddaf --- /dev/null +++ b/swift/downgrades/ba4171b90d0665b40e9e203bac9e3d4a0b2d03ec/upgrade.properties @@ -0,0 +1,56 @@ +description: Revert renaming the Function hierarchy +compatibility: full + +abstract_storage_decl_accessor_decls.rel: reorder abstract_storage_decl_accessors (int id, int index, int accessor) id index accessor +abstract_storage_decl_accessors.rel: delete + +destructor_decls.rel: reorder deinitializers (int id) id +deinitializers.rel: delete + +constructor_decls.rel: reorder initializers (int id) id +initializers.rel: delete + +accessor_decls.rel: reorder accessors (int id) id +accessors.rel: delete + +accessor_decl_is_getter.rel: reorder accessor_is_getter (int id) id +accessor_is_getter.rel: delete + +accessor_decl_is_setter.rel: reorder accessor_is_setter (int id) id +accessor_is_setter.rel: delete + +accessor_decl_is_will_set.rel: reorder accessor_is_will_set (int id) id +accessor_is_will_set.rel: delete + +accessor_decl_is_did_set.rel: reorder accessor_is_did_set (int id) id +accessor_is_did_set.rel: delete + +accessor_decl_is_read.rel: reorder accessor_is_read (int id) id +accessor_is_read.rel: delete + +accessor_decl_is_modify.rel: reorder accessor_is_modify (int id) id +accessor_is_modify.rel: delete + +accessor_decl_is_unsafe_address.rel: reorder accessor_is_unsafe_address (int id) id +accessor_is_unsafe_address.rel: delete + +accessor_decl_is_unsafe_mutable_address.rel: reorder accessor_is_unsafe_mutable_address (int id) id +accessor_is_unsafe_mutable_address.rel: delete + +concrete_func_decls.rel: reorder named_functions (int id) id +named_functions.rel: delete + +lazy_initializer_exprs.rel: reorder lazy_initialization_exprs (int id, int sub_expr) id sub_expr +lazy_initialization_exprs.rel: delete + +other_constructor_decl_ref_exprs.rel: reorder other_initializer_ref_exprs (int id, int constructor_decl) id constructor_decl +other_initializer_ref_exprs.rel: delete + +rebind_self_in_constructor_exprs.rel: reorder rebind_self_in_initializer_exprs (int id, int sub_expr, int self) id sub_expr self +rebind_self_in_initializer_exprs.rel: delete + +closure_exprs.rel: reorder explicit_closure_exprs (int id) id +explicit_closure_exprs.rel: delete + +constructor_ref_call_exprs.rel: reorder initializer_ref_call_exprs (int id) id +initializer_ref_call_exprs.rel: delete diff --git a/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/old.dbscheme b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/old.dbscheme new file mode 100644 index 00000000000..f937d9e6309 --- /dev/null +++ b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/old.dbscheme @@ -0,0 +1,2630 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/swift.dbscheme b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/swift.dbscheme new file mode 100644 index 00000000000..ba4171b90d0 --- /dev/null +++ b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/swift.dbscheme @@ -0,0 +1,2630 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @explicit_closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@explicit_closure_expr_or_none = + @explicit_closure_expr +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/upgrade.properties b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/upgrade.properties new file mode 100644 index 00000000000..cce7be2d078 --- /dev/null +++ b/swift/ql/lib/upgrades/f937d9e63094280b7ec0ef26c70310daad5c1f79/upgrade.properties @@ -0,0 +1,56 @@ +description: rename the Function hierarchy +compatibility: full + +abstract_storage_decl_accessors.rel: reorder abstract_storage_decl_accessor_decls (int id, int index, int accessor_decl) id index accessor_decl +abstract_storage_decl_accessor_decls.rel: delete + +deinitializers.rel: reorder destructor_decls (int id) id +destructor_decls.rel: delete + +initializers.rel: reorder constructor_decls (int id) id +constructor_decls.rel: delete + +accessors.rel: reorder accessor_decls (int id) id +accessor_decls.rel: delete + +accessor_is_getter.rel: reorder accessor_decl_is_getter (int id) id +accessor_decl_is_getter.rel: delete + +accessor_is_setter.rel: reorder accessor_decl_is_setter (int id) id +accessor_decl_is_setter.rel: delete + +accessor_is_will_set.rel: reorder accessor_decl_is_will_set (int id) id +accessor_decl_is_will_set.rel: delete + +accessor_is_did_set.rel: reorder accessor_decl_is_did_set (int id) id +accessor_decl_is_did_set.rel: delete + +accessor_is_read.rel: reorder accessor_decl_is_read (int id) id +accessor_decl_is_read.rel: delete + +accessor_is_modify.rel: reorder accessor_decl_is_modify (int id) id +accessor_decl_is_modify.rel: delete + +accessor_is_unsafe_address.rel: reorder accessor_decl_is_unsafe_address (int id) id +accessor_decl_is_unsafe_address.rel: delete + +accessor_is_unsafe_mutable_address.rel: reorder accessor_decl_is_unsafe_mutable_address (int id) id +accessor_decl_is_unsafe_mutable_address.rel: delete + +named_functions.rel: reorder concrete_func_decls (int id) id +concrete_func_decls.rel: delete + +lazy_initialization_exprs.rel: reorder lazy_initializer_exprs (int id, int sub_expr) id sub_expr +lazy_initializer_exprs.rel: delete + +other_initializer_ref_exprs.rel: reorder other_constructor_decl_ref_exprs (int id, int constructor_decl) id constructor_decl +other_constructor_decl_ref_exprs.rel: delete + +rebind_self_in_initializer_exprs.rel: reorder rebind_self_in_constructor_exprs (int id, int sub_expr, int self) id sub_expr self +rebind_self_in_constructor_exprs.rel: delete + +explicit_closure_exprs.rel: reorder closure_exprs (int id) id +closure_exprs.rel: delete + +initializer_ref_call_exprs.rel: reorder constructor_ref_call_exprs (int id) id +constructor_ref_call_exprs.rel: delete From 1aa1153ed6cf13d4836176417b97b7d2a9a84a90 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 26 Apr 2023 21:20:58 +0100 Subject: [PATCH 39/96] Go: Add `html/template` as XSS queries sanitizer --- go/ql/lib/semmle/go/security/Xss.qll | 16 ++++++++++++++++ .../Security/CWE-079/ReflectedXssGood.go | 6 ++++++ .../Security/CWE-079/StoredXssGood.go | 3 +++ 3 files changed, 25 insertions(+) diff --git a/go/ql/lib/semmle/go/security/Xss.qll b/go/ql/lib/semmle/go/security/Xss.qll index 98b6da02fe8..4c4c20e8a61 100644 --- a/go/ql/lib/semmle/go/security/Xss.qll +++ b/go/ql/lib/semmle/go/security/Xss.qll @@ -127,4 +127,20 @@ module SharedXss { ) } } + + /** + * A `Template` from `html/template` will HTML-escape data automatically + * and therefore acts as a sanitizer for XSS vulnerabilities. + */ + class HtmlTemplateSanitizer extends Sanitizer, DataFlow::Node { + HtmlTemplateSanitizer() { + exists(Method m, DataFlow::CallNode call | m = call.getCall().getTarget() | + m.hasQualifiedName("html/template", "Template", "ExecuteTemplate") and + call.getArgument(2) = this + or + m.hasQualifiedName("html/template", "Template", "Execute") and + call.getArgument(1) = this + ) + } + } } diff --git a/go/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.go b/go/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.go index 6f76ac4a434..d30b83e0704 100644 --- a/go/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.go +++ b/go/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.go @@ -3,16 +3,22 @@ package main import ( "fmt" "html" + "html/template" "net/http" ) func serve1() { + var template template.Template + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { r.ParseForm() username := r.Form.Get("username") if !isValidUsername(username) { // GOOD: a request parameter is escaped before being put into the response fmt.Fprintf(w, "%q is an unknown user", html.EscapeString(username)) + // GOOD: using html/template escapes values for us + template.Execute(w, username) + template.ExecuteTemplate(w, "test", username) } else { // TODO: do something exciting } diff --git a/go/ql/test/query-tests/Security/CWE-079/StoredXssGood.go b/go/ql/test/query-tests/Security/CWE-079/StoredXssGood.go index d73a205ff3f..364b9887466 100644 --- a/go/ql/test/query-tests/Security/CWE-079/StoredXssGood.go +++ b/go/ql/test/query-tests/Security/CWE-079/StoredXssGood.go @@ -2,15 +2,18 @@ package main import ( "html" + "html/template" "io" "io/ioutil" "net/http" ) func ListFiles1(w http.ResponseWriter, r *http.Request) { + var template template.Template files, _ := ioutil.ReadDir(".") for _, file := range files { io.WriteString(w, html.EscapeString(file.Name())+"\n") + template.Execute(w, file.Name()) } } From a541fdf5e5b9a7817385edc08ab1acbba94f8d57 Mon Sep 17 00:00:00 2001 From: amammad Date: Thu, 27 Apr 2023 08:30:46 +0200 Subject: [PATCH 40/96] v1.2 code quality improvements including commnets too --- .../Security/CWE-074/paramiko/paramiko.ql | 47 +++++++------------ 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql index 28db4e129b4..d296704b2d4 100644 --- a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql +++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql @@ -18,49 +18,34 @@ import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.ApiGraphs import DataFlow::PathGraph +private API::Node paramikoClient() { + result = API::moduleImport("paramiko").getMember("SSHClient").getReturn() +} + class ParamikoCMDInjectionConfiguration extends TaintTracking::Configuration { ParamikoCMDInjectionConfiguration() { this = "ParamikoCMDInjectionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + /** + * exec_command of `paramiko.SSHClient` class execute command on ssh target server + * the `paramiko.ProxyCommand` is equivalent of `ssh -o ProxyCommand="CMD"` + * and it run CMD on current system that running the ssh command + * the Sink related to proxy command is the `connect` method of `paramiko.SSHClient` class + */ override predicate isSink(DataFlow::Node sink) { - sink = - [ - API::moduleImport("paramiko") - .getMember("SSHClient") - .getReturn() - .getMember("exec_command") - .getACall() - .getArgByName("command"), - API::moduleImport("paramiko") - .getMember("SSHClient") - .getReturn() - .getMember("exec_command") - .getACall() - .getArg(0) - ] + sink = paramikoClient().getMember("exec_command").getACall().getParameter(0, "command").asSink() or - sink = - [ - API::moduleImport("paramiko") - .getMember("SSHClient") - .getReturn() - .getMember("connect") - .getACall() - .getArgByName("sock"), - API::moduleImport("paramiko") - .getMember("SSHClient") - .getReturn() - .getMember("connect") - .getACall() - .getArg(11) - ] + sink = paramikoClient().getMember("connect").getACall().getParameter(11, "sock").asSink() } + /** + * this additional taint step help taint tracking to find the vulnerable `connect` method of `paramiko.SSHClient` class + */ override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { exists(API::CallNode call | call = API::moduleImport("paramiko").getMember("ProxyCommand").getACall() and - nodeFrom = [call.getArg(0), call.getArgByName("command_line")] and + nodeFrom = call.getParameter(0, "command_line").asSink() and nodeTo = call ) } From 5a4fe1b4dadc6bb7eaceee789ec0b83faa1d91b7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 27 Apr 2023 10:55:36 +0200 Subject: [PATCH 41/96] JS: Stop complaining about comments in JSON files --- .../src/com/semmle/js/parser/JSONParser.java | 11 ++++------- .../tests/json/output/trap/comments.json.trap | 10 ---------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/parser/JSONParser.java b/javascript/extractor/src/com/semmle/js/parser/JSONParser.java index 2e7f7a96b5f..58f28644870 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSONParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSONParser.java @@ -21,6 +21,7 @@ import com.semmle.util.exception.Exceptions; import com.semmle.util.io.WholeIO; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -32,7 +33,6 @@ public class JSONParser { private int offset; private int length; private String src; - private List recoverableErrors; public static Pair> parseValue(String json) throws ParseError { JSONParser parser = new JSONParser(json); @@ -41,14 +41,13 @@ public class JSONParser { parser.consumeWhitespace(); if (parser.offset < parser.length) parser.raise("Expected end of input"); - return Pair.make(value, parser.recoverableErrors); + return Pair.make(value, Collections.emptyList()); } private JSONParser(String json) throws ParseError { this.line = 1; this.column = 0; this.offset = 0; - this.recoverableErrors = new ArrayList(); if (json == null) raise("Input string may not be null"); this.length = json.length(); @@ -351,17 +350,16 @@ public class JSONParser { } } - /** Skips the line comment starting at the current position and records a recoverable error. */ + /** Skips the line comment starting at the current position. */ private void skipLineComment() throws ParseError { Position pos = new Position(line, column, offset); char c; next(); next(); while ((c = peek()) != '\r' && c != '\n' && c != -1) next(); - recoverableErrors.add(new ParseError("Comments are not legal in JSON.", pos)); } - /** Skips the block comment starting at the current position and records a recoverable error. */ + /** Skips the block comment starting at the current position. */ private void skipBlockComment() throws ParseError { Position pos = new Position(line, column, offset); char c; @@ -376,7 +374,6 @@ public class JSONParser { break; } } while (true); - recoverableErrors.add(new ParseError("Comments are not legal in JSON.", pos)); } private void consume(char token) throws ParseError { diff --git a/javascript/extractor/tests/json/output/trap/comments.json.trap b/javascript/extractor/tests/json/output/trap/comments.json.trap index 320a172e3df..4d697f469a1 100644 --- a/javascript/extractor/tests/json/output/trap/comments.json.trap +++ b/javascript/extractor/tests/json/output/trap/comments.json.trap @@ -18,15 +18,5 @@ locations_default(#20003,#10000,3,12,3,18) json_locations(#20002,#20003) json_literals("world","""world""",#20002) json_properties(#20000,"hello",#20002) -#20004=* -json_errors(#20004,"Error: Comments are not legal in JSON.") -#20005=@"loc,{#10000},2,3,2,3" -locations_default(#20005,#10000,2,3,2,3) -json_locations(#20004,#20005) -#20006=* -json_errors(#20006,"Error: Comments are not legal in JSON.") -#20007=@"loc,{#10000},4,3,4,3" -locations_default(#20007,#10000,4,3,4,3) -json_locations(#20006,#20007) numlines(#10000,5,0,0) filetype(#10000,"json") From 410719fd9e5af80e38e241d29bd7850c8f8fedf5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 27 Apr 2023 10:57:38 +0200 Subject: [PATCH 42/96] Update JSONError.expected --- javascript/ql/test/library-tests/JSON/JSONError.expected | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/test/library-tests/JSON/JSONError.expected b/javascript/ql/test/library-tests/JSON/JSONError.expected index e63d3862491..e69de29bb2d 100644 --- a/javascript/ql/test/library-tests/JSON/JSONError.expected +++ b/javascript/ql/test/library-tests/JSON/JSONError.expected @@ -1 +0,0 @@ -| invalid.json:3:1:3:1 | Error: Comments are not legal in JSON. | From 1b366fc87aa052e265bc01141f38fd92a3c49f78 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 27 Apr 2023 11:49:34 +0200 Subject: [PATCH 43/96] C#: Re-factor ContentFlow into a parameterized module and use the new API. --- .../dataflow/internal/ContentDataFlow.qll | 450 +++++++++--------- 1 file changed, 221 insertions(+), 229 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll index 0259c748ec3..4fa60e9e3ae 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll @@ -1,156 +1,188 @@ /** * Provides classes for performing global (inter-procedural) * content-sensitive data flow analyses. + * + * Unlike `DataFlow::Global`, we allow for data to be stored (possibly nested) inside + * contents of sources and sinks. + * We track flow paths of the form + * + * ``` + * source --value-->* node + * (--read--> node --value-->* node)* + * --(non-value|value)-->* node + * (--store--> node --value-->* node)* + * --value-->* sink + * ``` + * + * where `--value-->` is a value-preserving flow step, `--read-->` is a read + * step, `--store-->` is a store step, and `--(non-value)-->` is a + * non-value-preserving flow step. + * + * That is, first a sequence of 0 or more reads, followed by 0 or more additional + * steps, followed by 0 or more stores, with value-preserving steps allowed in + * between all other steps. */ +private import csharp private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Private as DataFlowPrivate -module ContentDataFlow { - private import DataFlowImplSpecific::Private - private import DataFlowImplSpecific::Private as DataFlowPrivate - private import DataFlowImplForContentDataFlow as DF - - class Node = DF::Node; - - class FlowFeature = DF::FlowFeature; - - class ContentSet = DF::ContentSet; - - // predicate stageStats = DF::stageStats/8; +/** + * An input configuration for content data flow. + */ +signature module ContentConfigSig { /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends ContentDataFlowConfiguration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * // Optionally override `getAFeature`. - * // Optionally override `accessPathLimit`. - * // Optionally override `isRelevantContent`. - * } - * ``` - * - * Unlike `DataFlow::Configuration` (on which this class is based), we allow - * for data to be stored (possibly nested) inside contents of sources and sinks. - * We track flow paths of the form - * - * ``` - * source --value-->* node - * (--read--> node --value-->* node)* - * --(non-value|value)-->* node - * (--store--> node --value-->* node)* - * --value-->* sink - * ``` - * - * where `--value-->` is a value-preserving flow step, `--read-->` is a read - * step, `--store-->` is a store step, and `--(non-value)-->` is a - * non-value-preserving flow step. - * - * That is, first a sequence of 0 or more reads, followed by 0 or more additional - * steps, followed by 0 or more stores, with value-preserving steps allowed in - * between all other steps. + * Holds if `source` is a relevant data flow source. */ - abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } + predicate isSource(DataFlow::Node source); - /** - * Holds if `source` is a relevant data flow source. - */ - abstract predicate isSource(Node source); + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(DataFlow::Node sink); - /** - * Holds if `sink` is a relevant data flow sink. - */ - abstract predicate isSink(Node sink); + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() } - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrier(DataFlow::Node node) { none() } - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrier(Node node) { none() } + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + */ + default DataFlow::FlowFeature getAFeature() { none() } - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } + /** Gets a limit on the number of reads out of sources and number of stores into sinks. */ + default int accessPathLimit() { result = DataFlowPrivate::accessPathLimit() } - /** Gets a limit on the number of reads out of sources and number of stores into sinks. */ - int accessPathLimit() { result = DataFlowPrivate::accessPathLimit() } + /** Holds if `c` is relevant for reads out of sources or stores into sinks. */ + default predicate isRelevantContent(DataFlow::ContentSet c) { any() } +} - /** Holds if `c` is relevant for reads out of sources or stores into sinks. */ - predicate isRelevantContent(ContentSet c) { any() } +/** + * Constructs a global content data flow computation. + */ +module Global implements DataFlow::GlobalFlowSig { + private module FlowConfig implements DataFlow::StateConfigSig { + class FlowState = State; - /** - * Holds if data stored inside `sourceAp` on `source` flows to `sinkAp` inside `sink` - * for this configuration. `preservesValue` indicates whether any of the additional - * flow steps defined by `isAdditionalFlowStep` are needed. - * - * For the source access path, `sourceAp`, the top of the stack represents the content - * that was last read from. That is, if `sourceAp` is `Field1.Field2` (with `Field1` - * being the top of the stack), then there is flow from `source.Field2.Field1`. - * - * For the sink access path, `sinkAp`, the top of the stack represents the content - * that was last stored into. That is, if `sinkAp` is `Field1.Field2` (with `Field1` - * being the top of the stack), then there is flow into `sink.Field1.Field2`. - */ - final predicate hasFlow( - Node source, AccessPath sourceAp, Node sink, AccessPath sinkAp, boolean preservesValue - ) { - exists(DF::PathNode pathSource, DF::PathNode pathSink | - this.(ConfigurationAdapter).hasFlowPath(pathSource, pathSink) and - nodeReaches(pathSource, TAccessPathNil(), TAccessPathNil(), pathSink, sourceAp, sinkAp) and - source = pathSource.getNode() and - sink = pathSink.getNode() - | - pathSink.getState().(InitState).decode(preservesValue) - or - pathSink.getState().(ReadState).decode(_, preservesValue) - or - pathSink.getState().(StoreState).decode(_, preservesValue) + predicate isSource(DataFlow::Node source, FlowState state) { + ContentConfig::isSource(source) and + state.(InitState).decode(true) + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + ContentConfig::isSink(sink) and + ( + state instanceof InitState or + state instanceof StoreState or + state instanceof ReadState ) } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + storeStep(node1, state1, _, node2, state2) or + readStep(node1, state1, _, node2, state2) or + additionalStep(node1, state1, node2, state2) + } + + predicate isAdditionalFlowStep = ContentConfig::isAdditionalFlowStep/2; + + predicate isBarrier = ContentConfig::isBarrier/1; + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + DataFlow::FlowFeature getAFeature() { result = ContentConfig::getAFeature() } + + // needed to record reads/stores inside summarized callables + predicate includeHiddenNodes() { any() } + } + + private module Flow = DataFlow::GlobalWithState; + + import Flow + + /** + * Holds if data stored inside `sourceAp` on `source` flows to `sinkAp` inside `sink` + * for this configuration. `preservesValue` indicates whether any of the additional + * flow steps defined by `isAdditionalFlowStep` are needed. + * + * For the source access path, `sourceAp`, the top of the stack represents the content + * that was last read from. That is, if `sourceAp` is `Field1.Field2` (with `Field1` + * being the top of the stack), then there is flow from `source.Field2.Field1`. + * + * For the sink access path, `sinkAp`, the top of the stack represents the content + * that was last stored into. That is, if `sinkAp` is `Field1.Field2` (with `Field1` + * being the top of the stack), then there is flow into `sink.Field1.Field2`. + */ + additional predicate flow( + DataFlow::Node source, AccessPath sourceAp, DataFlow::Node sink, AccessPath sinkAp, + boolean preservesValue + ) { + exists(Flow::PathNode pathSource, Flow::PathNode pathSink | + Flow::flowPath(pathSource, pathSink) and + nodeReaches(pathSource, TAccessPathNil(), TAccessPathNil(), pathSink, sourceAp, sinkAp) and + source = pathSource.getNode() and + sink = pathSink.getNode() + | + pathSink.getState().(InitState).decode(preservesValue) + or + pathSink.getState().(ReadState).decode(_, preservesValue) + or + pathSink.getState().(StoreState).decode(_, preservesValue) + ) + } + + private newtype TState = + TInitState(boolean preservesValue) { preservesValue in [false, true] } or + TStoreState(int size, boolean preservesValue) { + size in [1 .. ContentConfig::accessPathLimit()] and + preservesValue in [false, true] + } or + TReadState(int size, boolean preservesValue) { + size in [1 .. ContentConfig::accessPathLimit()] and + preservesValue in [false, true] + } + + abstract private class State extends TState { + abstract string toString(); } /** A flow state representing no reads or stores. */ - private class InitState extends DF::FlowState { + private class InitState extends State, TInitState { private boolean preservesValue_; - InitState() { this = "Init(" + preservesValue_ + ")" and preservesValue_ in [false, true] } + InitState() { this = TInitState(preservesValue_) } + + override string toString() { result = "Init(" + preservesValue_ + ")" } predicate decode(boolean preservesValue) { preservesValue = preservesValue_ } } /** A flow state representing that content has been stored into. */ - private class StoreState extends DF::FlowState { + private class StoreState extends State, TStoreState { private boolean preservesValue_; private int size_; - StoreState() { - preservesValue_ in [false, true] and - size_ in [1 .. any(Configuration c).accessPathLimit()] and - this = "StoreState(" + size_ + "," + preservesValue_ + ")" - } + StoreState() { this = TStoreState(size_, preservesValue_) } + + override string toString() { result = "StoreState(" + size_ + "," + preservesValue_ + ")" } predicate decode(int size, boolean preservesValue) { size = size_ and preservesValue = preservesValue_ @@ -158,15 +190,13 @@ module ContentDataFlow { } /** A flow state representing that content has been read from. */ - private class ReadState extends DF::FlowState { + private class ReadState extends State, TReadState { private boolean preservesValue_; private int size_; - ReadState() { - preservesValue_ in [false, true] and - size_ in [1 .. any(Configuration c).accessPathLimit()] and - this = "ReadState(" + size_ + "," + preservesValue_ + ")" - } + ReadState() { this = TReadState(size_, preservesValue_) } + + override string toString() { result = "ReadState(" + size_ + "," + preservesValue_ + ")" } predicate decode(int size, boolean preservesValue) { size = size_ and preservesValue = preservesValue_ @@ -174,12 +204,12 @@ module ContentDataFlow { } private predicate storeStep( - Node node1, DF::FlowState state1, ContentSet c, Node node2, StoreState state2, - Configuration config + DataFlow::Node node1, State state1, DataFlow::ContentSet c, DataFlow::Node node2, + StoreState state2 ) { exists(boolean preservesValue, int size | storeSet(node1, c, node2, _, _) and - config.isRelevantContent(c) and + ContentConfig::isRelevantContent(c) and state2.decode(size + 1, preservesValue) | state1.(InitState).decode(preservesValue) and size = 0 @@ -191,12 +221,12 @@ module ContentDataFlow { } private predicate readStep( - Node node1, DF::FlowState state1, ContentSet c, Node node2, ReadState state2, - Configuration config + DataFlow::Node node1, State state1, DataFlow::ContentSet c, DataFlow::Node node2, + ReadState state2 ) { exists(int size | readSet(node1, c, node2) and - config.isRelevantContent(c) and + ContentConfig::isRelevantContent(c) and state2.decode(size + 1, true) | state1.(InitState).decode(true) and @@ -207,9 +237,9 @@ module ContentDataFlow { } private predicate additionalStep( - Node node1, DF::FlowState state1, Node node2, DF::FlowState state2, Configuration config + DataFlow::Node node1, State state1, DataFlow::Node node2, State state2 ) { - config.isAdditionalFlowStep(node1, node2) and + ContentConfig::isAdditionalFlowStep(node1, node2) and ( state1 instanceof InitState and state2.(InitState).decode(false) @@ -221,49 +251,18 @@ module ContentDataFlow { ) } - private class ConfigurationAdapter extends DF::Configuration instanceof Configuration { - final override predicate isSource(Node source, DF::FlowState state) { - Configuration.super.isSource(source) and - state.(InitState).decode(true) - } - - final override predicate isSink(Node sink, DF::FlowState state) { - Configuration.super.isSink(sink) and - ( - state instanceof InitState or - state instanceof StoreState or - state instanceof ReadState - ) - } - - final override predicate isAdditionalFlowStep( - Node node1, DF::FlowState state1, Node node2, DF::FlowState state2 - ) { - storeStep(node1, state1, _, node2, state2, this) or - readStep(node1, state1, _, node2, state2, this) or - additionalStep(node1, state1, node2, state2, this) - } - - final override predicate isBarrier(Node node) { Configuration.super.isBarrier(node) } - - final override FlowFeature getAFeature() { result = Configuration.super.getAFeature() } - - // needed to record reads/stores inside summarized callables - final override predicate includeHiddenNodes() { any() } - } - private newtype TAccessPath = TAccessPathNil() or - TAccessPathCons(ContentSet head, AccessPath tail) { + TAccessPathCons(DataFlow::ContentSet head, AccessPath tail) { nodeReachesStore(_, _, _, _, head, _, tail) or nodeReachesRead(_, _, _, _, head, tail, _) } /** An access path. */ - class AccessPath extends TAccessPath { + additional class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - ContentSet getHead() { this = TAccessPathCons(result, _) } + DataFlow::ContentSet getHead() { this = TAccessPathCons(result, _) } /** Gets the tail of this access path, if any. */ AccessPath getTail() { this = TAccessPathCons(_, result) } @@ -278,7 +277,7 @@ module ContentDataFlow { this = TAccessPathNil() and result = "" or - exists(ContentSet head, AccessPath tail | + exists(DataFlow::ContentSet head, AccessPath tail | this = TAccessPathCons(head, tail) and result = head + "." + tail ) @@ -287,7 +286,7 @@ module ContentDataFlow { // important to use `edges` and not `PathNode::getASuccessor()`, as the latter // is not pruned for reachability - private predicate pathSucc = DF::PathGraph::edges/2; + private predicate pathSucc = Flow::PathGraph::edges/2; /** * Provides a big-step flow relation, where flow stops at read/store steps that @@ -295,10 +294,10 @@ module ContentDataFlow { * summarized callables can be recorded as well. */ private module BigStepFlow { - private predicate reachesSink(DF::PathNode node) { - any(ConfigurationAdapter config).isSink(node.getNode(), node.getState()) + private predicate reachesSink(Flow::PathNode node) { + FlowConfig::isSink(node.getNode(), node.getState()) or - exists(DF::PathNode mid | + exists(Flow::PathNode mid | pathSucc(node, mid) and reachesSink(mid) ) @@ -309,76 +308,72 @@ module ContentDataFlow { * in the big-step relation. */ pragma[nomagic] - private predicate excludeStep(DF::PathNode pred, DF::PathNode succ) { + private predicate excludeStep(Flow::PathNode pred, Flow::PathNode succ) { pathSucc(pred, succ) and ( // we need to record reads/stores inside summarized callables - DF::PathGraph::subpaths(pred, _, _, succ) + Flow::PathGraph::subpaths(pred, _, _, succ) or // only allow flow into a summarized callable, as part of the big-step // relation, when flow can reach a sink without going back out - DF::PathGraph::subpaths(pred, succ, _, _) and + Flow::PathGraph::subpaths(pred, succ, _, _) and not reachesSink(succ) or // needed to record store steps - storeStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState(), - pred.getConfiguration()) + storeStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState()) or // needed to record read steps - readStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState(), - pred.getConfiguration()) + readStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState()) ) } pragma[nomagic] - private DataFlowCallable getEnclosingCallableImpl(DF::PathNode node) { + private DataFlowCallable getEnclosingCallableImpl(Flow::PathNode node) { result = getNodeEnclosingCallable(node.getNode()) } pragma[inline] - private DataFlowCallable getEnclosingCallable(DF::PathNode node) { + private DataFlowCallable getEnclosingCallable(Flow::PathNode node) { pragma[only_bind_into](result) = getEnclosingCallableImpl(pragma[only_bind_out](node)) } pragma[nomagic] - private predicate bigStepEntry(DF::PathNode node) { - node.getConfiguration() instanceof Configuration and + private predicate bigStepEntry(Flow::PathNode node) { ( - any(ConfigurationAdapter config).isSource(node.getNode(), node.getState()) + FlowConfig::isSource(node.getNode(), node.getState()) or excludeStep(_, node) or - DF::PathGraph::subpaths(_, node, _, _) + Flow::PathGraph::subpaths(_, node, _, _) ) } pragma[nomagic] - private predicate bigStepExit(DF::PathNode node) { - node.getConfiguration() instanceof Configuration and + private predicate bigStepExit(Flow::PathNode node) { ( bigStepEntry(node) or - any(ConfigurationAdapter config).isSink(node.getNode(), node.getState()) + FlowConfig::isSink(node.getNode(), node.getState()) or excludeStep(node, _) or - DF::PathGraph::subpaths(_, _, node, _) + Flow::PathGraph::subpaths(_, _, node, _) ) } pragma[nomagic] - private predicate step(DF::PathNode pred, DF::PathNode succ) { + private predicate step(Flow::PathNode pred, Flow::PathNode succ) { pathSucc(pred, succ) and not excludeStep(pred, succ) } pragma[nomagic] - private predicate stepRec(DF::PathNode pred, DF::PathNode succ) { + private predicate stepRec(Flow::PathNode pred, Flow::PathNode succ) { step(pred, succ) and not bigStepEntry(pred) } - private predicate stepRecPlus(DF::PathNode n1, DF::PathNode n2) = fastTC(stepRec/2)(n1, n2) + private predicate stepRecPlus(Flow::PathNode n1, Flow::PathNode n2) = fastTC(stepRec/2)(n1, n2) /** * Holds if there is flow `pathSucc+(pred) = succ`, and such a flow path does @@ -386,8 +381,8 @@ module ContentDataFlow { * steps. */ pragma[nomagic] - private predicate bigStep(DF::PathNode pred, DF::PathNode succ) { - exists(DF::PathNode mid | + private predicate bigStep(Flow::PathNode pred, Flow::PathNode succ) { + exists(Flow::PathNode mid | bigStepEntry(pred) and step(pred, mid) | @@ -399,13 +394,13 @@ module ContentDataFlow { } pragma[nomagic] - predicate bigStepNotLocal(DF::PathNode pred, DF::PathNode succ) { + predicate bigStepNotLocal(Flow::PathNode pred, Flow::PathNode succ) { bigStep(pred, succ) and not getEnclosingCallable(pred) = getEnclosingCallable(succ) } pragma[nomagic] - predicate bigStepMaybeLocal(DF::PathNode pred, DF::PathNode succ) { + predicate bigStepMaybeLocal(Flow::PathNode pred, Flow::PathNode succ) { bigStep(pred, succ) and getEnclosingCallable(pred) = getEnclosingCallable(succ) } @@ -422,55 +417,54 @@ module ContentDataFlow { */ pragma[nomagic] private predicate nodeReaches( - DF::PathNode source, AccessPath scReads, AccessPath scStores, DF::PathNode node, + Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node, AccessPath reads, AccessPath stores ) { - exists(ConfigurationAdapter config | - node = source and - reads = scReads and - stores = scStores - | - config.hasFlowPath(source, _) and + node = source and + reads = scReads and + stores = scStores and + ( + Flow::flowPath(source, _) and scReads = TAccessPathNil() and scStores = TAccessPathNil() or // the argument in a sub path can be reached, so we start flow from the sub path // parameter, while recording the read/store summary context - exists(DF::PathNode arg | + exists(Flow::PathNode arg | nodeReachesSubpathArg(_, _, _, arg, scReads, scStores) and - DF::PathGraph::subpaths(arg, source, _, _) + Flow::PathGraph::subpaths(arg, source, _, _) ) ) or - exists(DF::PathNode mid | + exists(Flow::PathNode mid | nodeReaches(source, scReads, scStores, mid, reads, stores) and BigStepFlow::bigStepMaybeLocal(mid, node) ) or - exists(DF::PathNode mid | + exists(Flow::PathNode mid | nodeReaches(source, scReads, scStores, mid, reads, stores) and BigStepFlow::bigStepNotLocal(mid, node) and // when flow is not local, we cannot flow back out, so we may stop // flow early when computing summary flow - any(ConfigurationAdapter config).hasFlowPath(source, _) and + Flow::flowPath(source, _) and scReads = TAccessPathNil() and scStores = TAccessPathNil() ) or // store step - exists(AccessPath storesMid, ContentSet c | + exists(AccessPath storesMid, DataFlow::ContentSet c | nodeReachesStore(source, scReads, scStores, node, c, reads, storesMid) and stores = TAccessPathCons(c, storesMid) ) or // read step - exists(AccessPath readsMid, ContentSet c | + exists(AccessPath readsMid, DataFlow::ContentSet c | nodeReachesRead(source, scReads, scStores, node, c, readsMid, stores) and reads = TAccessPathCons(c, readsMid) ) or // flow-through step; match outer stores/reads with inner store/read summary contexts - exists(DF::PathNode mid, AccessPath innerScReads, AccessPath innerScStores | + exists(Flow::PathNode mid, AccessPath innerScReads, AccessPath innerScStores | nodeReachesSubpathArg(source, scReads, scStores, mid, innerScReads, innerScStores) and subpathArgReachesOut(mid, innerScReads, innerScStores, node, reads, stores) ) @@ -478,47 +472,45 @@ module ContentDataFlow { pragma[nomagic] private predicate nodeReachesStore( - DF::PathNode source, AccessPath scReads, AccessPath scStores, DF::PathNode node, ContentSet c, - AccessPath reads, AccessPath stores + Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node, + DataFlow::ContentSet c, AccessPath reads, AccessPath stores ) { - exists(DF::PathNode mid | + exists(Flow::PathNode mid | nodeReaches(source, scReads, scStores, mid, reads, stores) and - storeStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState(), - node.getConfiguration()) and + storeStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState()) and pathSucc(mid, node) ) } pragma[nomagic] private predicate nodeReachesRead( - DF::PathNode source, AccessPath scReads, AccessPath scStores, DF::PathNode node, ContentSet c, - AccessPath reads, AccessPath stores + Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node, + DataFlow::ContentSet c, AccessPath reads, AccessPath stores ) { - exists(DF::PathNode mid | + exists(Flow::PathNode mid | nodeReaches(source, scReads, scStores, mid, reads, stores) and - readStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState(), - node.getConfiguration()) and + readStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState()) and pathSucc(mid, node) ) } pragma[nomagic] private predicate nodeReachesSubpathArg( - DF::PathNode source, AccessPath scReads, AccessPath scStores, DF::PathNode arg, + Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode arg, AccessPath reads, AccessPath stores ) { nodeReaches(source, scReads, scStores, arg, reads, stores) and - DF::PathGraph::subpaths(arg, _, _, _) + Flow::PathGraph::subpaths(arg, _, _, _) } pragma[nomagic] private predicate subpathArgReachesOut( - DF::PathNode arg, AccessPath scReads, AccessPath scStores, DF::PathNode out, AccessPath reads, - AccessPath stores + Flow::PathNode arg, AccessPath scReads, AccessPath scStores, Flow::PathNode out, + AccessPath reads, AccessPath stores ) { - exists(DF::PathNode source, DF::PathNode ret | + exists(Flow::PathNode source, Flow::PathNode ret | nodeReaches(source, scReads, scStores, ret, reads, stores) and - DF::PathGraph::subpaths(arg, source, ret, out) + Flow::PathGraph::subpaths(arg, source, ret, out) ) } } From 8517f114774f6c0cfed54ce21a354cfef7af59b2 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 27 Apr 2023 11:49:53 +0200 Subject: [PATCH 44/96] C#: Re-factor the test case for ContentFlow. --- .../dataflow/content/ContentFlow.ql | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql b/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql index 07a510a62ce..459f49cc8d5 100644 --- a/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql +++ b/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql @@ -1,23 +1,23 @@ import csharp -import semmle.code.csharp.dataflow.internal.ContentDataFlow +import semmle.code.csharp.dataflow.internal.ContentDataFlow as ContentDataFlow -class Conf extends ContentDataFlow::Configuration { - Conf() { this = "ContentFlowConf" } +module ContentConfig implements ContentDataFlow::ContentConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodCall mc | mc.getTarget().hasUndecoratedName("Sink") and mc.getAnArgument() = sink.asExpr() ) } - override int accessPathLimit() { result = 2 } + int accessPathLimit() { result = 2 } } +module ContentFlow = ContentDataFlow::Global; + from - Conf conf, ContentDataFlow::Node source, ContentDataFlow::AccessPath sourceAp, - ContentDataFlow::Node sink, ContentDataFlow::AccessPath sinkAp, boolean preservesValue -where conf.hasFlow(source, sourceAp, sink, sinkAp, preservesValue) + DataFlow::Node source, ContentFlow::AccessPath sourceAp, DataFlow::Node sink, + ContentFlow::AccessPath sinkAp, boolean preservesValue +where ContentFlow::flow(source, sourceAp, sink, sinkAp, preservesValue) select source, sourceAp, sink, sinkAp, preservesValue From cda26ba7c0194016973edac4eb89d9c27ccb7f91 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 13 Apr 2023 15:31:02 +0200 Subject: [PATCH 45/96] Dataflow: Split TypedContent in store relation. --- .../java/dataflow/internal/DataFlowImpl.qll | 62 +++++++++---------- .../dataflow/internal/DataFlowImplCommon.qll | 6 +- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index cd8e992c980..509bbe5a04d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -390,10 +390,10 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx(NodeEx node1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType) { + store(pragma[only_bind_into](node1.asNode()), tc, c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +478,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, _, node, _, _) ) or // read @@ -570,12 +570,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, _, c, node, _, _) ) } @@ -709,11 +708,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, _, c, mid, _, _) ) } @@ -803,15 +801,12 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1048,7 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1306,7 +1301,7 @@ module Impl { ) { exists(DataFlowType contentType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + PrevStage::storeStepCand(node1, apa1, tc, _, node2, contentType, _) and typecheckStore(ap1, contentType) ) } @@ -1659,10 +1654,10 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, tc, c, node2, contentType, containerType) and revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) @@ -1688,7 +1683,7 @@ module Impl { private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _, _, _) } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil @@ -2003,7 +1998,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2021,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -3386,7 +3381,7 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, _, node, _, _) and state = mid.getState() and cc = mid.getCallContext() } @@ -3593,7 +3588,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -4271,7 +4266,7 @@ module Impl { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and + storeEx(midNode, tc, _, node, contentType, _) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and compatibleTypes(ap1.getType(), contentType) @@ -4522,12 +4517,11 @@ module Impl { private predicate revPartialPathStoreStep( PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, _, c, midNode, _, _) and + ap.getHead() = c ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..723799fa91a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -831,8 +831,10 @@ private module Cached { * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store(Node node1, TypedContent tc, Content c, Node node2, DataFlowType contentType, DataFlowType containerType) { + tc.getContent() = c and + tc.getContainerType() = containerType and + store(node1, c, node2, contentType, containerType) } /** From b84b1a46d6b3aca7ee6a6d6629b3bbd2f9410d49 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 14 Apr 2023 11:41:27 +0200 Subject: [PATCH 46/96] Dataflow: Duplicate accesspath type info as separate column. --- .../java/dataflow/internal/DataFlowImpl.qll | 200 +++++++++++------- 1 file changed, 119 insertions(+), 81 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 509bbe5a04d..545461b4d4e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1058,6 +1058,8 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ; + class Ap; class ApNil extends Ap; @@ -1067,6 +1069,8 @@ module Impl { ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); + bindingset[tc, tail] Ap apCons(TypedContent tc, Ap tail); @@ -1115,7 +1119,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, ApNil ap, LocalCc lcc ); predicate flowOutOfCall( @@ -1129,14 +1133,19 @@ module Impl { bindingset[node, state, ap] predicate filter(NodeEx node, FlowState state, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1178,49 +1187,51 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and filter(node, state, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and argAp = apNone() and summaryCtx = TParamNodeNone() and + t = getNodeTyp(node) and ap = getApNil(node) and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, t0, ap0, apa0) and localCc = getLocalCc(mid, cc) | - localStep(mid, state0, node, state, true, _, localCc) and + localStep(mid, state0, node, state, true, _, _, localCc) and + t = t0 and ap = ap0 and apa = apa0 or - localStep(mid, state0, node, state, false, ap, localCc) and + localStep(mid, state0, node, state, false, t, ap, localCc) and ap0 instanceof ApNil and apa = getApprox(ap) ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and @@ -1228,41 +1239,43 @@ module Impl { ) or exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + fwdFlow(mid, state, _, _, _, _, nil) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and argAp = apNone() and + t = getNodeTyp(node) and ap = getApNil(node) and apa = getApprox(ap) ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + fwdFlow(mid, state0, _, _, _, _, nil) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and argAp = apNone() and + t = getNodeTyp(node) and ap = getApNil(node) and apa = getApprox(ap) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + exists(TypedContent tc, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, tc, t, node, state, cc, summaryCtx, argAp) and ap = apCons(tc, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and @@ -1276,7 +1289,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1288,7 +1301,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1296,24 +1309,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + NodeEx node1, Typ t1, Ap ap1, TypedContent tc, Typ t2, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, _, node2, contentType, _) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, _, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and + fwdFlowStore(_, t1, tail, tc, t2, _, _, _, _, _) and tc.getContent() = c and cons = apCons(tc, tail) ) @@ -1333,11 +1348,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1346,10 +1361,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1359,12 +1374,12 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1375,19 +1390,19 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, t, ap, apa) and fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, t, ap, apa, ret, _, _, innerArgApa) } /** @@ -1400,7 +1415,7 @@ module Impl { ParamNodeEx p, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, _, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1409,14 +1424,17 @@ module Impl { pragma[nomagic] private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + fwdFlowStore(node1, _, ap1, tc, _, node2, _, _, _, _) and ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + readStepFwd(_, ap2, tc.getContent(), _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] @@ -1424,7 +1442,7 @@ module Impl { DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + fwdFlowThrough0(call, _, state, ccc, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, innerArgApa) } @@ -1448,7 +1466,7 @@ module Impl { exists(ApApprox argApa | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argAp), argApa) and returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) @@ -1460,7 +1478,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, ap, apa) ) } @@ -1471,7 +1489,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1489,14 +1507,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1507,13 +1525,13 @@ module Impl { ap instanceof ApNil or exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, _) and + localStep(node, state, mid, state0, true, _, _, _) and revFlow(mid, state0, returnCtx, returnAp, ap) ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + fwdFlow(node, pragma[only_bind_into](state), _, _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _, _) and revFlow(mid, state0, returnCtx, returnAp, nil) and ap instanceof ApNil ) @@ -1526,7 +1544,7 @@ module Impl { ) or exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + fwdFlow(node, _, _, _, _, _, ap) and additionalJumpStep(node, mid) and revFlow(pragma[only_bind_into](mid), state, _, _, nil) and returnCtx = TReturnCtxNone() and @@ -1535,7 +1553,7 @@ module Impl { ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + fwdFlow(node, _, _, _, _, _, ap) and additionalJumpStateStep(node, state, mid, state0) and revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and returnCtx = TReturnCtxNone() and @@ -1747,13 +1765,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _)) and fields = count(TypedContent f0 | fwdConsCand(f0, _)) and conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, t, ap) ) or fwd = false and @@ -1860,6 +1878,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1873,6 +1893,8 @@ module Impl { ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } + bindingset[tc, tail] Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } @@ -1896,7 +1918,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, ApNil ap, LocalCc lcc ) { ( preservesValue = true and @@ -1910,6 +1932,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and + exists(t) and exists(ap) and exists(lcc) } @@ -1940,8 +1963,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2128,6 +2151,8 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; @@ -2138,6 +2163,8 @@ module Impl { PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) } + Typ getTyp(DataFlowType t) { result = t } + bindingset[tc, tail] Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } @@ -2158,9 +2185,10 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, ApproxAccessPathFrontNil ap, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and + ap.getType() = t and exists(lcc) } @@ -2192,11 +2220,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2207,6 +2235,8 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; @@ -2217,6 +2247,8 @@ module Impl { PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) } + Typ getTyp(DataFlowType t) { result = t } + bindingset[tc, tail] Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } @@ -2238,9 +2270,10 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, ApNil ap, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and + ap.getType() = t and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2311,11 +2344,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2330,7 +2363,7 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), _, apf) ) } @@ -2530,6 +2563,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2541,6 +2576,8 @@ module Impl { PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) } + Typ getTyp(DataFlowType t) { result = t } + bindingset[tc, tail] Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } @@ -2562,9 +2599,10 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, ApNil ap, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and + ap.getType() = t and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2595,8 +2633,8 @@ module Impl { predicate filter(NodeEx node, FlowState state, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2609,7 +2647,7 @@ module Impl { Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + TAccessPathApproxSome(apa), _, apa0) ) } From c79daf0116dcb098a311dcb2d2ae32dd4349517b Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 17 Apr 2023 16:25:47 +0200 Subject: [PATCH 47/96] Dataflow: Duplicate accesspath type info of the tail in cons relations. --- .../java/dataflow/internal/DataFlowImpl.qll | 126 +++++++++--------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 545461b4d4e..04a732e54aa 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1071,8 +1071,8 @@ module Impl { Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[tc, t, tail] + Ap apCons(TypedContent tc, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1263,7 +1263,7 @@ module Impl { // store exists(TypedContent tc, Typ t0, Ap ap0 | fwdFlowStore(_, t0, ap0, tc, t, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + ap = apCons(tc, t0, ap0) and apa = getApprox(ap) ) or @@ -1330,7 +1330,7 @@ module Impl { exists(TypedContent tc | fwdFlowStore(_, t1, tail, tc, t2, _, _, _, _, _) and tc.getContent() = c and - cons = apCons(tc, tail) + cons = apCons(tc, t1, tail) ) } @@ -1423,9 +1423,9 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, _, ap1, tc, _, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, tc, _, node2, _, _, _, _) and + ap2 = apCons(tc, t1, ap1) and readStepFwd(_, ap2, tc.getContent(), _, _) } @@ -1563,7 +1563,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1602,11 +1602,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and + storeStepFwd(node, t, ap, tc, mid, ap0) and tc.getContent() = c } @@ -1676,7 +1676,7 @@ module Impl { ) { exists(Ap ap2 | PrevStage::storeStepCand(node1, _, tc, c, node2, contentType, containerType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowStore(ap2, c, ap1, _, node1, _, tc, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1685,7 +1685,7 @@ module Impl { exists(Ap ap1, Ap ap2 | revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and readStepFwd(node1, ap1, c, node2, ap2) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, _) ) } @@ -1699,21 +1699,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(TypedContent tc, Typ t, Ap ap) { storeStepFwd(_, t, ap, tc, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _, _, _) } + private predicate revConsCand(TypedContent tc, Typ t, Ap ap) { + exists(Ap ap2, Content c | + revFlowStore(ap2, c, ap, t, _, _, tc, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(TypedContent head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(TypedContent tc, Typ t, Ap ap) { + revConsCand(tc, t, ap) and validAp(ap) } @@ -1766,8 +1771,8 @@ module Impl { ) { fwd = true and nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _, _)) and + conscand = count(TypedContent f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap | @@ -1776,8 +1781,8 @@ module Impl { or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(TypedContent f0 | consCand(f0, _, _)) and + conscand = count(TypedContent f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1895,8 +1900,8 @@ module Impl { Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[tc, t, tail] + Ap apCons(TypedContent tc, Typ t, Ap tail) { result = true and exists(tc) and exists(t) and exists(tail) } class ApHeadContent = Unit; @@ -2165,8 +2170,8 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[tc, t, tail] + Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getAHead() = tc and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; @@ -2249,8 +2254,8 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[tc, t, tail] + Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getHead() = tc and exists(t) and exists(tail) } class ApHeadContent = Content; @@ -2373,7 +2378,7 @@ module Impl { */ private predicate expensiveLen2unfolding(TypedContent tc) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(tc, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) @@ -2390,11 +2395,11 @@ module Impl { private newtype TAccessPathApprox = TNil(DataFlowType t) or TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and + Stage4::consCand(tc, t, TFrontNil(t)) and not expensiveLen2unfolding(tc) } or TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + Stage4::consCand(tc1, _, TFrontHead(tc2)) and len in [2 .. accessPathLimit()] and not expensiveLen2unfolding(tc1) } or @@ -2421,8 +2426,8 @@ module Impl { abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { @@ -2440,7 +2445,7 @@ module Impl { override AccessPathFront getFront() { result = TFrontNil(t) } - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } @@ -2464,7 +2469,7 @@ module Impl { override AccessPathFront getFront() { result = TFrontHead(tc) } - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and typ = t and tail = TNil(t) } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { @@ -2488,15 +2493,16 @@ module Impl { override AccessPathFront getFront() { result = TFrontHead(tc1) } - override AccessPathApprox pop(TypedContent head) { + override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc1 and + typ = tc2.getContainerType() and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(tc2, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(tc2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(tc2, len - 1) ) } } @@ -2521,32 +2527,30 @@ module Impl { override AccessPathFront getFront() { result = TFrontHead(tc) } - override AccessPathApprox pop(TypedContent head) { + override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(TypedContent tc2 | Stage4::consCand(tc, typ, TFrontHead(tc2)) | + tail = TConsCons(tc2, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(tc2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(tc2, len - 1) ) or exists(DataFlowType t | len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) + Stage4::consCand(tc, t, TFrontNil(t)) and + typ = t and + tail = TNil(t) ) ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto the `t,apa` pair. */ + private AccessPathApprox push(TypedContent tc, DataFlowType t, AccessPathApprox apa) { result.isCons(tc, t, apa) } private newtype TAccessPathApproxOption = TAccessPathApproxNone() or @@ -2578,8 +2582,8 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[tc, t, tail] + Ap apCons(TypedContent tc, Typ t, Ap tail) { result = push(tc, t, tail) } class ApHeadContent = Content; @@ -2710,8 +2714,8 @@ module Impl { tc = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(tc, t, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2738,9 +2742,9 @@ module Impl { } private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + exists(TypedContent head, DataFlowType t | + apa.isCons(head, t, result) and + Stage5::consCand(head, t, result) ) } @@ -2962,7 +2966,7 @@ module Impl { override TypedContent getHead() { result = head1 } override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and + Stage5::consCand(head1, head2.getContainerType(), result.getApprox()) and result.getHead() = head2 and result.length() = len - 1 } @@ -2994,7 +2998,7 @@ module Impl { override TypedContent getHead() { result = head } override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + Stage5::consCand(head, _, result.getApprox()) and result.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head) } From 209d9143bef71da2e703fc7a9dafe61bcfc38ef2 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 20 Apr 2023 12:45:53 +0200 Subject: [PATCH 48/96] Dataflow: Add type column to filter predicate --- .../java/dataflow/internal/DataFlowImpl.qll | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 04a732e54aa..77473bd9232 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1130,8 +1130,8 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); bindingset[typ, contentType] predicate typecheckStore(Typ typ, DataFlowType contentType); @@ -1192,7 +1192,7 @@ module Impl { ) { fwdFlow0(node, state, cc, summaryCtx, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] @@ -1955,9 +1955,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -2214,10 +2215,10 @@ module Impl { pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2337,11 +2338,11 @@ module Impl { pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2633,8 +2634,8 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] From 5a027b95bd2ef5d69c1b30a296c3fec9035d394c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 20 Apr 2023 14:19:55 +0200 Subject: [PATCH 49/96] Dataflow: Duplicate accesspath type info in PathNode and pathStep. --- .../java/dataflow/internal/DataFlowImpl.qll | 113 ++++++++++-------- 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 77473bd9232..7fe616e1b60 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2666,9 +2666,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2690,9 +2693,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParameterPosition getParameterPos() { p.isParameterOf(_, result) } @@ -2823,16 +2827,17 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil(t) or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -3215,9 +3220,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3227,11 +3233,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3246,7 +3254,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil(t) } predicate isAtSink() { @@ -3343,7 +3352,7 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and @@ -3353,6 +3362,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3363,16 +3373,17 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + pathNode(mid, midnode, state0, cc, sc, _, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap.(AccessPathNil).getType() = t and ap0 instanceof AccessPathNil ) or @@ -3380,6 +3391,7 @@ module Impl { state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3387,25 +3399,30 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil(t) or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil(t) or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, t, cc)) and sc = mid.getSummaryCtx() or exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + // TODO: replace push/pop with isCons + // ap0.isCons(tc, t, ap) + exists(t) and sc = mid.getSummaryCtx() or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and t = mid.getType() and ap = mid.getAp() and sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] @@ -3421,10 +3438,10 @@ module Impl { pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, DataFlowType t, CallContext cc ) { ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, _, node, _, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, _, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3478,10 +3495,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3501,10 +3518,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3521,13 +3538,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3544,11 +3561,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3559,11 +3576,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3573,10 +3590,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3589,12 +3606,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _) and + pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3605,9 +3622,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3617,11 +3634,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3648,12 +3665,12 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists(ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) From fd36304da262caa85a2cb1b32acb289438907643 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 20 Apr 2023 14:33:00 +0200 Subject: [PATCH 50/96] Dataflow: Add type to PathNode.toString --- .../lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 7fe616e1b60..5d0dad5cf32 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3077,9 +3077,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) From 11c05257d4389b9e686b6264f0af7869ba0aa1e2 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 24 Apr 2023 11:19:59 +0200 Subject: [PATCH 51/96] Dataflow: Duplicate accesspath type info in partial flow. --- .../java/dataflow/internal/DataFlowImpl.qll | 103 ++++++++++-------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 5d0dad5cf32..a16aa18b3df 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -4004,17 +4004,18 @@ module Impl { private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -4042,9 +4043,9 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead().getContent()) and @@ -4053,7 +4054,7 @@ module Impl { expectsContentEx(node, ap.getHead().getContent()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4113,11 +4114,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4158,9 +4155,10 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, t, ap) } NodeEx getNodeEx() { result = node } @@ -4174,11 +4172,13 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getType(), result.getAp()) } predicate isSource() { @@ -4229,7 +4229,7 @@ module Impl { private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4239,6 +4239,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4248,6 +4249,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and mid.getAp() instanceof PartialAccessPathNil and + t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and @@ -4256,6 +4258,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and mid.getAp() instanceof PartialAccessPathNil and + t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) ) or @@ -4265,6 +4268,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4274,6 +4278,7 @@ module Impl { sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and mid.getAp() instanceof PartialAccessPathNil and + t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and @@ -4282,32 +4287,33 @@ module Impl { sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and mid.getAp() instanceof PartialAccessPathNil and + t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() @@ -4318,55 +4324,58 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { - exists(NodeEx midNode, DataFlowType contentType | + exists(NodeEx midNode, DataFlowType contentType, TypedContent tc | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, _, node, contentType, _) and + storeEx(midNode, tc, c, node, contentType, t2) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd(DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead().getContent() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4376,10 +4385,10 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4388,13 +4397,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4403,19 +4413,19 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and @@ -4430,7 +4440,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4440,6 +4450,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4447,19 +4458,19 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } From 77b09f3660c749c10ea26a94663212e5701f3929 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 24 Apr 2023 11:31:11 +0200 Subject: [PATCH 52/96] Dataflow: Add type to partial flow summary context --- .../java/dataflow/internal/DataFlowImpl.qll | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index a16aa18b3df..9d1c23585d7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3987,7 +3987,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -4004,18 +4008,19 @@ module Impl { private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, t, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( @@ -4043,9 +4048,9 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, t, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and not clearsContentEx(node, ap.getHead().getContent()) and @@ -4155,10 +4160,11 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, t, ap) } + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) } NodeEx getNodeEx() { result = node } @@ -4172,13 +4178,15 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + DataFlowType getType() { result = t } PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getType(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4187,6 +4195,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4229,7 +4238,7 @@ module Impl { private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4239,6 +4248,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and t = mid.getType() and ap = mid.getAp() or @@ -4248,6 +4258,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) @@ -4257,6 +4268,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) @@ -4268,7 +4280,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - t = mid.getType() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4277,6 +4290,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) @@ -4286,6 +4300,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and ap = TPartialNil(node.getDataFlowType()) @@ -4295,7 +4310,8 @@ module Impl { cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or exists(DataFlowType t0, PartialAccessPath ap0, Content c | partialPathReadStep(mid, t0, ap0, c, node, cc) and @@ -4303,20 +4319,23 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, t, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4422,14 +4441,15 @@ module Impl { private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, DataFlowType t, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4440,7 +4460,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, DataFlowType t, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4450,6 +4470,7 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and t = mid.getType() and ap = mid.getAp() ) @@ -4460,9 +4481,9 @@ module Impl { DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, t, ap) + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } From e5d36ff46130017799e679b00fddbdcccc2d52ff Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 24 Apr 2023 14:24:51 +0200 Subject: [PATCH 53/96] Dataflow: Add type to stage 2-5 summary ctx. --- .../java/dataflow/internal/DataFlowImpl.qll | 133 ++++++++++-------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 9d1c23585d7..86147550ba5 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -1058,7 +1059,9 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { - class Typ; + class Typ { + string toString(); + } class Ap; @@ -1141,6 +1144,10 @@ module Impl { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + pragma[nomagic] private Typ getNodeTyp(NodeEx node) { PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) @@ -1187,29 +1194,30 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, t, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, t, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and t = getNodeTyp(node) and @@ -1217,7 +1225,7 @@ module Impl { apa = getApprox(ap) or exists(NodeEx mid, FlowState state0, Typ t0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, t0, ap0, apa0) and + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap0, apa0) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, _, localCc) and @@ -1231,18 +1239,20 @@ module Impl { ) or exists(NodeEx mid | - fwdFlow(mid, state, _, _, _, t, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, _, nil) and + fwdFlow(mid, state, _, _, _, _, _, nil) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and t = getNodeTyp(node) and ap = getApNil(node) and @@ -1250,10 +1260,11 @@ module Impl { ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, _, nil) and + fwdFlow(mid, state0, _, _, _, _, _, nil) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and t = getNodeTyp(node) and ap = getApNil(node) and @@ -1262,26 +1273,27 @@ module Impl { or // store exists(TypedContent tc, Typ t0, Ap ap0 | - fwdFlowStore(_, t0, ap0, tc, t, node, state, cc, summaryCtx, argAp) and + fwdFlowStore(_, t0, ap0, tc, t, node, state, cc, summaryCtx, argT, argAp) and ap = apCons(tc, t0, ap0) and apa = getApprox(ap) ) or // read exists(Typ t0, Ap ap0, Content c | - fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, t, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1289,7 +1301,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, t, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1301,7 +1313,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, t, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1310,10 +1322,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( NodeEx node1, Typ t1, Ap ap1, TypedContent tc, Typ t2, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, t1, ap1, apa1) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and PrevStage::storeStepCand(node1, apa1, tc, _, node2, contentType, containerType) and t2 = getTyp(containerType) and typecheckStore(t1, contentType) @@ -1328,7 +1340,7 @@ module Impl { pragma[nomagic] private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { exists(TypedContent tc | - fwdFlowStore(_, t1, tail, tc, t2, _, _, _, _, _) and + fwdFlowStore(_, t1, tail, tc, t2, _, _, _, _, _, _) and tc.getContent() = c and cons = apCons(tc, t1, tail) ) @@ -1349,10 +1361,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, t, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1361,10 +1373,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, t, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1373,12 +1385,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + TypOption::some(argT), pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and @@ -1389,20 +1402,20 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, t, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, t, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, innerArgApa) } /** @@ -1411,11 +1424,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, + ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, _, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1424,7 +1437,7 @@ module Impl { pragma[nomagic] private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, t1, ap1, tc, _, node2, _, _, _, _) and + fwdFlowStore(node1, t1, ap1, tc, _, node2, _, _, _, _, _) and ap2 = apCons(tc, t1, ap1) and readStepFwd(_, ap2, tc.getContent(), _, _) } @@ -1432,7 +1445,7 @@ module Impl { pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { exists(Typ t1 | - fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _) and + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and fwdFlowConsCand(t1, ap1, c, _, ap2) ) } @@ -1440,19 +1453,19 @@ module Impl { pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1463,11 +1476,11 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1478,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1489,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1507,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1530,7 +1543,7 @@ module Impl { ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, _, ap) and + fwdFlow(node, pragma[only_bind_into](state), _, _, _, _, _, ap) and localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _, _) and revFlow(mid, state0, returnCtx, returnAp, nil) and ap instanceof ApNil @@ -1544,7 +1557,7 @@ module Impl { ) or exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, _, ap) and + fwdFlow(node, _, _, _, _, _, _, ap) and additionalJumpStep(node, mid) and revFlow(pragma[only_bind_into](mid), state, _, _, nil) and returnCtx = TReturnCtxNone() and @@ -1553,7 +1566,7 @@ module Impl { ) or exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, _, ap) and + fwdFlow(node, _, _, _, _, _, _, ap) and additionalJumpStateStep(node, state, mid, state0) and revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and returnCtx = TReturnCtxNone() and @@ -1590,7 +1603,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1665,7 +1678,7 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } @@ -1733,7 +1746,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1741,7 +1754,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1770,13 +1783,13 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and fields = count(TypedContent f0 | fwdConsCand(f0, _, _)) and conscand = count(TypedContent f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Typ t, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, t, ap) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap) ) or fwd = false and @@ -2369,7 +2382,7 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), _, apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, apf) ) } @@ -2651,7 +2664,7 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, TAccessPathApproxSome(apa), _, apa0) ) } @@ -2669,7 +2682,7 @@ module Impl { TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { exists(AccessPathApprox apa | ap.getApprox() = apa | Stage5::parameterMayFlowThrough(p, apa) and - Stage5::fwdFlow(p, state, _, _, _, t, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and Stage5::revFlow(p, state, _) ) } From 2cf58fccf72c160905c7273fb07d84e58ceb3d50 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 11:13:19 +0200 Subject: [PATCH 54/96] Dataflow: Remove type from PartialAccessPath. --- .../java/dataflow/internal/DataFlowImpl.qll | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 86147550ba5..67a3304c412 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3903,46 +3903,35 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. */ private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TPartialNil(_) and result = 0 + this = TPartialNil() and result = 0 or this = TPartialCons(_, result) } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } } private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + override string toString() { result = "" } } private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" ) } } @@ -4030,7 +4019,7 @@ module Impl { sc3 = TSummaryCtx3None() and sc4 = TSummaryCtx4None() and t = node.getDataFlowType() and - ap = TPartialNil(node.getDataFlowType()) and + ap = TPartialNil() and exists(explorationLimit()) or partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and @@ -4066,10 +4055,10 @@ module Impl { partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode then compatibleTypes(node.getDataFlowType(), t) @@ -4274,7 +4263,7 @@ module Impl { sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and - ap = TPartialNil(node.getDataFlowType()) + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and @@ -4284,7 +4273,7 @@ module Impl { sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and - ap = TPartialNil(node.getDataFlowType()) + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4306,7 +4295,7 @@ module Impl { sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and - ap = TPartialNil(node.getDataFlowType()) + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and @@ -4316,7 +4305,7 @@ module Impl { sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and t = node.getDataFlowType() and - ap = TPartialNil(node.getDataFlowType()) + ap = TPartialNil() or partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and @@ -4359,12 +4348,12 @@ module Impl { PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, DataFlowType t2, PartialAccessPath ap2 ) { - exists(NodeEx midNode, DataFlowType contentType, TypedContent tc | + exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, c, node, contentType, t2) and - ap2.getHead() = tc and + storeEx(midNode, _, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and compatibleTypes(t1, contentType) ) @@ -4384,7 +4373,7 @@ module Impl { t = mid.getType() and ap = mid.getAp() and read(midNode, c, node) and - ap.getHead().getContent() = c and + ap.getHead() = c and cc = mid.getCallContext() ) } From 933d2fbb9f694c39425dad60685ee766321492f8 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 11:20:46 +0200 Subject: [PATCH 55/96] Dataflow: Replace RevPartialAccessPath with the now identical PartialAccessPath. --- .../java/dataflow/internal/DataFlowImpl.qll | 82 ++++++------------- 1 file changed, 24 insertions(+), 58 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 67a3304c412..3e57071501d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3936,40 +3936,6 @@ module Impl { } } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - private predicate relevantState(FlowState state) { sourceNode(_, state) or sinkNode(_, state) or @@ -4005,7 +3971,7 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( @@ -4027,13 +3993,13 @@ module Impl { } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -4208,7 +4174,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4222,7 +4188,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4234,7 +4200,7 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } @@ -4501,7 +4467,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4515,15 +4481,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4537,15 +4503,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4553,7 +4519,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4588,8 +4554,8 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, + PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4601,13 +4567,13 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4620,7 +4586,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4636,7 +4602,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4653,7 +4619,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4663,7 +4629,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and From 69202d2daef19cb3947873f823e62eb49d731a3c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 11:41:38 +0200 Subject: [PATCH 56/96] Dataflow: Include type in post-stage-5 tail relation. --- .../java/dataflow/internal/DataFlowImpl.qll | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 3e57071501d..3cc741695d0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2759,10 +2759,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head, DataFlowType t | - apa.isCons(head, t, result) and - Stage5::consCand(head, t, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(TypedContent head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2808,7 +2808,7 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = @@ -2817,16 +2817,17 @@ module Impl { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, _, tail.getApprox()) ) } or TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, _, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or TAccessPathCons1(TypedContent head, int len) { From 142479eeb70107e1e456d6acd08bc5d87ce4dd74 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 11:50:50 +0200 Subject: [PATCH 57/96] Dataflow: Duplicate type info for AccessPath tails. --- .../java/dataflow/internal/DataFlowImpl.qll | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 3cc741695d0..ae69a0da3eb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2813,19 +2813,19 @@ module Impl { private newtype TAccessPath = TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathCons(TypedContent head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - hasTail(apa, _, tail.getApprox()) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + TAccessPathCons2(TypedContent head1, DataFlowType t, TypedContent head2, int len) { exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and - hasTail(apa, _, tail) and + hasTail(apa, t, tail) and head1 = apa.getHead() and head2 = tail.getHead() ) @@ -2925,9 +2925,10 @@ module Impl { private class AccessPathCons extends AccessPath, TAccessPathCons { private TypedContent head; + private DataFlowType t; private AccessPath tail; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head, t, tail) } override TypedContent getHead() { result = head } @@ -2937,7 +2938,7 @@ module Impl { pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head, t) and tail instanceof AccessPathNil or result = TConsCons(head, tail.getHead(), this.length()) or @@ -2948,15 +2949,13 @@ module Impl { override int length() { result = 1 + tail.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) + tail = TAccessPathNil(_) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) or result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, _, tc3, len) | result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true or result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false @@ -2978,15 +2977,16 @@ module Impl { private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { private TypedContent head1; + private DataFlowType t; private TypedContent head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } override TypedContent getHead() { result = head1 } override AccessPath getTail() { - Stage5::consCand(head1, head2.getContainerType(), result.getApprox()) and + Stage5::consCand(head1, t, result.getApprox()) and result.getHead() = head2 and result.length() = len - 1 } From 52f50b8d9d920360091df52abf3513c2417e28cd Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 12:08:40 +0200 Subject: [PATCH 58/96] Dataflow: Replace AccessPath push/pop with isCons. --- .../java/dataflow/internal/DataFlowImpl.qll | 105 ++++++++++-------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index ae69a0da3eb..fc9d0c8704e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2881,6 +2881,9 @@ module Impl { /** Gets the tail of this access path, if any. */ abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail); + /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2892,15 +2895,6 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { @@ -2914,6 +2908,8 @@ module Impl { override AccessPath getTail() { none() } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { none() } + override AccessPathFrontNil getFront() { result = TFrontNil(t) } override AccessPathApproxNil getApprox() { result = TNil(t) } @@ -2924,47 +2920,51 @@ module Impl { } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; + private TypedContent head_; private DataFlowType t; - private AccessPath tail; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, t, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override TypedContent getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override AccessPath getTail() { result = tail_ } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, t) and tail instanceof AccessPathNil + result = TConsNil(head_, t) and tail_ instanceof AccessPathNil or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - tail = TAccessPathNil(_) and + tail_ = TAccessPathNil(_) and needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, _, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(TypedContent tc2, TypedContent tc3, int len | tail_ = TAccessPathCons2(tc2, _, tc3, len) | + result = head_ + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + result = head_ + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false ) or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + exists(TypedContent tc2, int len | tail_ = TAccessPathCons1(tc2, len) | + result = head_ + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } @@ -2991,6 +2991,14 @@ module Impl { result.length() = len - 1 } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 + } + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { @@ -3010,27 +3018,32 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private TypedContent head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override TypedContent getHead() { result = head_ } override AccessPath getTail() { - Stage5::consCand(head, _, result.getApprox()) and result.length() = len - 1 + Stage5::consCand(head_, _, result.getApprox()) and result.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and tail.length() = len - 1 + } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } + + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3421,14 +3434,17 @@ module Impl { t = node.getDataFlowType() and ap = TAccessPathNil(t) or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, t, cc)) and - sc = mid.getSummaryCtx() + exists(TypedContent tc, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, tc, t, cc) and + ap.isCons(tc, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - // TODO: replace push/pop with isCons - // ap0.isCons(tc, t, ap) - exists(t) and - sc = mid.getSummaryCtx() + exists(TypedContent tc, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, tc, cc) and + ap0.isCons(tc, t, ap) and + sc = mid.getSummaryCtx() + ) or pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or @@ -3450,8 +3466,9 @@ module Impl { pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, DataFlowType t, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, TypedContent tc, DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and Stage5::storeStepCand(mid.getNodeEx(), _, tc, _, node, _, t) and state = mid.getState() and From 95b95e5c278d2057d7a82ae0c9a2450f51ff2200 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 13:21:41 +0200 Subject: [PATCH 59/96] Dataflow: Duplicate type info for AccessPathApprox tails. --- .../java/dataflow/internal/DataFlowImpl.qll | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index fc9d0c8704e..2f87e7c6bf1 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2412,8 +2412,8 @@ module Impl { Stage4::consCand(tc, t, TFrontNil(t)) and not expensiveLen2unfolding(tc) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, _, TFrontHead(tc2)) and + TConsCons(TypedContent tc1, DataFlowType t, TypedContent tc2, int len) { + Stage4::consCand(tc1, t, TFrontHead(tc2)) and len in [2 .. accessPathLimit()] and not expensiveLen2unfolding(tc1) } or @@ -2488,10 +2488,11 @@ module Impl { private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { private TypedContent tc1; + private DataFlowType t; private TypedContent tc2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(tc1, t, tc2, len) } override string toString() { if len = 2 @@ -2509,9 +2510,9 @@ module Impl { override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc1 and - typ = tc2.getContainerType() and + typ = t and ( - tail = TConsCons(tc2, _, len - 1) + tail = TConsCons(tc2, _, _, len - 1) or len = 2 and tail = TConsNil(tc2, _) @@ -2545,7 +2546,7 @@ module Impl { head = tc and ( exists(TypedContent tc2 | Stage4::consCand(tc, typ, TFrontHead(tc2)) | - tail = TConsCons(tc2, _, len - 1) + tail = TConsCons(tc2, _, _, len - 1) or len = 2 and tail = TConsNil(tc2, _) @@ -2940,7 +2941,7 @@ module Impl { override AccessPathApproxCons getApprox() { result = TConsNil(head_, t) and tail_ instanceof AccessPathNil or - result = TConsCons(head_, tail_.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or result = TCons1(head_, this.length()) } @@ -3002,7 +3003,7 @@ module Impl { override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } From 748bcba0ae256ead7a2a9f5553d713d4a7a4d53f Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 13:54:17 +0200 Subject: [PATCH 60/96] Dataflow: Eliminate now-redundant type in nil accesspath approximations. --- .../java/dataflow/internal/DataFlowImpl.qll | 146 ++++++------------ .../dataflow/internal/DataFlowImplCommon.qll | 30 +--- 2 files changed, 52 insertions(+), 124 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 2f87e7c6bf1..4c11bb076dc 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1070,8 +1070,6 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); - Typ getTyp(DataFlowType t); bindingset[tc, t, tail] @@ -1122,7 +1120,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - Typ t, ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1221,21 +1219,18 @@ module Impl { argAp = apNone() and summaryCtx = TParamNodeNone() and t = getNodeTyp(node) and - ap = getApNil(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Typ t0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | - localStep(mid, state0, node, state, true, _, _, localCc) and - t = t0 and - ap = ap0 and - apa = apa0 + localStep(mid, state0, node, state, true, _, localCc) and + t = t0 or - localStep(mid, state0, node, state, false, t, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | @@ -1247,28 +1242,26 @@ module Impl { argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() and t = getNodeTyp(node) and - ap = getApNil(node) and - apa = getApprox(ap) + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() and t = getNodeTyp(node) and - ap = getApNil(node) and - apa = getApprox(ap) + ap instanceof ApNil ) or // store @@ -1538,14 +1531,13 @@ module Impl { ap instanceof ApNil or exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, _, _) and + localStep(node, state, mid, state0, true, _, _) and revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, _, _, ap) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + exists(NodeEx mid, FlowState state0 | + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1556,19 +1548,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1909,8 +1899,6 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } - Typ getTyp(DataFlowType t) { any() } bindingset[tc, t, tail] @@ -1936,7 +1924,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - Typ t, ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ) { ( preservesValue = true and @@ -1951,7 +1939,6 @@ module Impl { additionalLocalStateStep(node1, state1, node2, state2) ) and exists(t) and - exists(ap) and exists(lcc) } @@ -2178,10 +2165,6 @@ module Impl { PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - Typ getTyp(DataFlowType t) { result = t } bindingset[tc, t, tail] @@ -2204,10 +2187,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and - ap.getType() = t and exists(lcc) } @@ -2262,10 +2244,6 @@ module Impl { PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - Typ getTyp(DataFlowType t) { result = t } bindingset[tc, t, tail] @@ -2289,10 +2267,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and - ap.getType() = t and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2407,9 +2384,9 @@ module Impl { } private newtype TAccessPathApprox = - TNil(DataFlowType t) or + TNil() or TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, t, TFrontNil(t)) and + Stage4::consCand(tc, t, TFrontNil()) and not expensiveLen2unfolding(tc) } or TConsCons(TypedContent tc1, DataFlowType t, TypedContent tc2, int len) { @@ -2436,8 +2413,6 @@ module Impl { abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ @@ -2445,19 +2420,13 @@ module Impl { } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } override TypedContent getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } + override AccessPathFront getFront() { result = TFrontNil() } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { none() } } @@ -2479,11 +2448,9 @@ module Impl { override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } - override AccessPathFront getFront() { result = TFrontHead(tc) } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and typ = t and tail = TNil(t) } + override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and typ = t and tail = TNil() } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { @@ -2504,8 +2471,6 @@ module Impl { override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } - override AccessPathFront getFront() { result = TFrontHead(tc1) } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { @@ -2538,8 +2503,6 @@ module Impl { override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } - override AccessPathFront getFront() { result = TFrontHead(tc) } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { @@ -2554,12 +2517,9 @@ module Impl { tail = TCons1(tc2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, t, TFrontNil(t)) and - typ = t and - tail = TNil(t) - ) + len = 1 and + Stage4::consCand(tc, typ, TFrontNil()) and + tail = TNil() ) } } @@ -2591,10 +2551,6 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - Typ getTyp(DataFlowType t) { result = t } bindingset[tc, t, tail] @@ -2618,10 +2574,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and - ap.getType() = t and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2813,7 +2768,7 @@ module Impl { } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or + TAccessPathNil() or TAccessPathCons(TypedContent head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and @@ -2849,7 +2804,7 @@ module Impl { sourceCallCtx(cc) and sc instanceof SummaryCtxNone and t = node.getDataFlowType() and - ap = TAccessPathNil(t) + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and @@ -2899,25 +2854,19 @@ module Impl { } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - override TypedContent getHead() { none() } override AccessPath getTail() { none() } override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { none() } - override AccessPathFrontNil getFront() { result = TFrontNil(t) } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { @@ -2939,7 +2888,7 @@ module Impl { pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head_, t) and tail_ instanceof AccessPathNil + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or result = TConsCons(head_, t, tail_.getHead(), this.length()) or @@ -2950,7 +2899,7 @@ module Impl { override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - tail_ = TAccessPathNil(_) and + tail_ = TAccessPathNil() and needsSuffix = false and result = head_.toString() + "]" + concat(" : " + ppReprType(t)) or @@ -3281,7 +3230,7 @@ module Impl { sourceCallCtx(cc) and sc instanceof SummaryCtxNone and t = node.getDataFlowType() and - ap = TAccessPathNil(t) + ap = TAccessPathNil() } predicate isAtSink() { @@ -3406,11 +3355,10 @@ module Impl { localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, _, ap0, localCC) and + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and localFlowBigStep(midnode, state0, node, state, false, t, localCC) and - ap.(AccessPathNil).getType() = t and - ap0 instanceof AccessPathNil + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and @@ -3426,14 +3374,14 @@ module Impl { sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and t = node.getDataFlowType() and - ap = TAccessPathNil(t) + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and t = node.getDataFlowType() and - ap = TAccessPathNil(t) + ap = TAccessPathNil() or exists(TypedContent tc, DataFlowType t0, AccessPath ap0 | pathStoreStep(mid, node, state, t0, ap0, tc, t, cc) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 723799fa91a..b404214f40e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -957,12 +957,12 @@ private module Cached { cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or + TFrontNil() or TFrontHead(TypedContent tc) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or + TApproxFrontNil() or TApproxFrontHead(TypedContentApprox tc) cached @@ -1415,8 +1415,6 @@ class TypedContentApprox extends MkTypedContentApprox { abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); TypedContentApprox getHead() { this = TApproxFrontHead(result) } @@ -1431,13 +1429,7 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } @@ -1449,8 +1441,6 @@ class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead override string toString() { result = tc.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - override boolean toBoolNonEmpty() { result = true } } @@ -1493,23 +1483,15 @@ class TypedContent extends MkTypedContent { abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); TypedContent getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { @@ -1519,8 +1501,6 @@ class AccessPathFrontHead extends AccessPathFront, TFrontHead { override string toString() { result = tc.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } } From ff3e45e1baf32e54d546de3511a64bf761c285f8 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 14:14:18 +0200 Subject: [PATCH 61/96] Dataflow: Eliminate TypedContentApprox. --- .../java/dataflow/internal/DataFlowImpl.qll | 6 +- .../dataflow/internal/DataFlowImplCommon.qll | 56 +++---------------- 2 files changed, 12 insertions(+), 50 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 4c11bb076dc..6d235098129 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2168,12 +2168,12 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getAHead() = tc and exists(t) and exists(tail) } + Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getAHead() = tc.getContent() and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2203,7 +2203,7 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index b404214f40e..226bd5f9330 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -934,27 +934,9 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - cached newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = TFrontNil() or @@ -963,7 +945,7 @@ private module Cached { cached newtype TApproxAccessPathFront = TApproxFrontNil() or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1389,26 +1371,6 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ @@ -1417,13 +1379,13 @@ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } @@ -1435,11 +1397,11 @@ class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1501,7 +1463,7 @@ class AccessPathFrontHead extends AccessPathFront, TFrontHead { override string toString() { result = tc.toString() } - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = tc.getContent() } } /** An optional access path front. */ From 123534a676f2479f04105b5a76f9ac43078768d3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 25 Apr 2023 14:29:50 +0200 Subject: [PATCH 62/96] Dataflow: Eliminate front type in AccessPathFront. --- .../java/dataflow/internal/DataFlowImpl.qll | 28 +++++++++---------- .../dataflow/internal/DataFlowImplCommon.qll | 12 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 6d235098129..ba0ac353bcd 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2247,12 +2247,12 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getHead() = tc and exists(t) and exists(tail) } + Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getHead() = tc.getContent() and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2313,7 +2313,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2321,7 +2321,7 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } @@ -2372,9 +2372,9 @@ module Impl { tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(tc, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc.getContent())) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc.getContent())) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and @@ -2390,7 +2390,7 @@ module Impl { not expensiveLen2unfolding(tc) } or TConsCons(TypedContent tc1, DataFlowType t, TypedContent tc2, int len) { - Stage4::consCand(tc1, t, TFrontHead(tc2)) and + Stage4::consCand(tc1, t, TFrontHead(tc2.getContent())) and len in [2 .. accessPathLimit()] and not expensiveLen2unfolding(tc1) } or @@ -2448,7 +2448,7 @@ module Impl { override int len() { result = 1 } - override AccessPathFront getFront() { result = TFrontHead(tc) } + override AccessPathFront getFront() { result = TFrontHead(tc.getContent()) } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and typ = t and tail = TNil() } } @@ -2471,7 +2471,7 @@ module Impl { override int len() { result = len } - override AccessPathFront getFront() { result = TFrontHead(tc1) } + override AccessPathFront getFront() { result = TFrontHead(tc1.getContent()) } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc1 and @@ -2503,12 +2503,12 @@ module Impl { override int len() { result = len } - override AccessPathFront getFront() { result = TFrontHead(tc) } + override AccessPathFront getFront() { result = TFrontHead(tc.getContent()) } override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and ( - exists(TypedContent tc2 | Stage4::consCand(tc, typ, TFrontHead(tc2)) | + exists(TypedContent tc2 | Stage4::consCand(tc, typ, TFrontHead(tc2.getContent())) | tail = TConsCons(tc2, _, _, len - 1) or len = 2 and @@ -2884,7 +2884,7 @@ module Impl { head = head_ and typ = t and tail = tail_ } - override AccessPathFrontHead getFront() { result = TFrontHead(head_) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_.getContent()) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { @@ -2949,7 +2949,7 @@ module Impl { tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + override AccessPathFrontHead getFront() { result = TFrontHead(head1.getContent()) } override AccessPathApproxCons getApprox() { result = TConsCons(head1, t, head2, len) or @@ -2984,7 +2984,7 @@ module Impl { Stage5::consCand(head_, typ, tail.getApprox()) and tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head_) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_.getContent()) } override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 226bd5f9330..50ee53c4f78 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -940,7 +940,7 @@ private module Cached { cached newtype TAccessPathFront = TFrontNil() or - TFrontHead(TypedContent tc) + TFrontHead(Content c) cached newtype TApproxAccessPathFront = @@ -1447,7 +1447,7 @@ abstract class AccessPathFront extends TAccessPathFront { abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { @@ -1457,13 +1457,13 @@ class AccessPathFrontNil extends AccessPathFront, TFrontNil { } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override ApproxAccessPathFront toApprox() { result.getAHead() = tc.getContent() } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ From a2fa97ac22d2860ab4029a00014b05aad717a974 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 09:59:25 +0200 Subject: [PATCH 63/96] Dataflow: Replace TypedContent with Content in access paths. --- .../java/dataflow/internal/DataFlowImpl.qll | 290 +++++++++--------- 1 file changed, 144 insertions(+), 146 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index ba0ac353bcd..cb1bef4e383 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1072,8 +1072,8 @@ module Impl { Typ getTyp(DataFlowType t); - bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1265,9 +1265,9 @@ module Impl { ) or // store - exists(TypedContent tc, Typ t0, Ap ap0 | - fwdFlowStore(_, t0, ap0, tc, t, node, state, cc, summaryCtx, argT, argAp) and - ap = apCons(tc, t0, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or @@ -1314,12 +1314,12 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Typ t1, Ap ap1, TypedContent tc, Typ t2, NodeEx node2, FlowState state, Cc cc, + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, _, node2, contentType, containerType) and + PrevStage::storeStepCand(node1, apa1, _, c, node2, contentType, containerType) and t2 = getTyp(containerType) and typecheckStore(t1, contentType) ) @@ -1332,11 +1332,8 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, t1, tail, tc, t2, _, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, t1, tail) - ) + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1429,10 +1426,10 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, t1, ap1, tc, _, node2, _, _, _, _, _) and - ap2 = apCons(tc, t1, ap1) and - readStepFwd(_, ap2, tc.getContent(), _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } pragma[nomagic] @@ -1566,7 +1563,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, _, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1605,12 +1602,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, t, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1679,7 +1675,7 @@ module Impl { ) { exists(Ap ap2 | PrevStage::storeStepCand(node1, _, tc, c, node2, contentType, containerType) and - revFlowStore(ap2, c, ap1, _, node1, _, tc, node2, _, _) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1688,7 +1684,7 @@ module Impl { exists(Ap ap1, Ap ap2 | revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and readStepFwd(node1, ap1, c, node2, ap2) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, _) + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) ) } @@ -1702,11 +1698,11 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Typ t, Ap ap) { storeStepFwd(_, t, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Typ t, Ap ap) { - exists(Ap ap2, Content c | - revFlowStore(ap2, c, ap, t, _, _, tc, _, _, _) and + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and revFlowConsCand(ap2, c, ap) ) } @@ -1714,14 +1710,14 @@ module Impl { private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Typ t, Ap tail | + exists(Content head, Typ t, Ap tail | consCand(head, t, tail) and ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Typ t, Ap ap) { - revConsCand(tc, t, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1774,8 +1770,8 @@ module Impl { ) { fwd = true and nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, _)) and - conscand = count(TypedContent f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap | @@ -1784,8 +1780,8 @@ module Impl { or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _, _)) and - conscand = count(TypedContent f0, Typ t, Ap ap | consCand(f0, t, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1901,8 +1897,8 @@ module Impl { Typ getTyp(DataFlowType t) { any() } - bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result = true and exists(tc) and exists(t) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result = true and exists(c) and exists(t) and exists(tail) } class ApHeadContent = Unit; @@ -2167,8 +2163,8 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getAHead() = tc.getContent() and exists(t) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; @@ -2246,8 +2242,8 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result.getHead() = tc.getContent() and exists(t) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; @@ -2364,168 +2360,169 @@ module Impl { } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(tc, t, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc.getContent())) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc.getContent())) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = TNil() or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, t, TFrontNil()) and - not expensiveLen2unfolding(tc) + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, DataFlowType t, TypedContent tc2, int len) { - Stage4::consCand(tc1, t, TFrontHead(tc2.getContent())) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); abstract AccessPathFront getFront(); /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ - abstract predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail); + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { override string toString() { result = "" } - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } override AccessPathFront getFront() { result = TFrontNil() } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override AccessPathFront getFront() { result = TFrontHead(tc.getContent()) } + override AccessPathFront getFront() { result = TFrontHead(c) } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { head = tc and typ = t and tail = TNil() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c and typ = t and tail = TNil() } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; + private Content c1; private DataFlowType t; - private TypedContent tc2; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, t, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override AccessPathFront getFront() { result = TFrontHead(tc1.getContent()) } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and typ = t and ( - tail = TConsCons(tc2, _, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - tail = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - tail = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override AccessPathFront getFront() { result = TFrontHead(tc.getContent()) } + override AccessPathFront getFront() { result = TFrontHead(c) } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPathApprox tail) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, typ, TFrontHead(tc2.getContent())) | - tail = TConsCons(tc2, _, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - tail = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - tail = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or len = 1 and - Stage4::consCand(tc, typ, TFrontNil()) and + Stage4::consCand(c, typ, TFrontNil()) and tail = TNil() ) } } - /** Gets the access path obtained by pushing `tc` onto the `t,apa` pair. */ - private AccessPathApprox push(TypedContent tc, DataFlowType t, AccessPathApprox apa) { result.isCons(tc, t, apa) } + /** Gets the access path obtained by pushing `c` onto the `t,apa` pair. */ + private AccessPathApprox push(Content c, DataFlowType t, AccessPathApprox apa) { result.isCons(c, t, apa) } private newtype TAccessPathApproxOption = TAccessPathApproxNone() or @@ -2553,13 +2550,13 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, t, tail] - Ap apCons(TypedContent tc, Typ t, Ap tail) { result = push(tc, t, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result = push(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2684,12 +2681,12 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = strictcount(DataFlowType t, AccessPathFront apf | - Stage5::consCand(tc, t, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + Stage5::consCand(c, t, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2716,7 +2713,7 @@ module Impl { } private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { - exists(TypedContent head | + exists(Content head | apa.isCons(head, t, tail) and Stage5::consCand(head, t, tail) ) @@ -2727,7 +2724,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2769,14 +2766,14 @@ module Impl { private newtype TAccessPath = TAccessPathNil() or - TAccessPathCons(TypedContent head, DataFlowType t, AccessPath tail) { + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, DataFlowType t, TypedContent head2, int len) { + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and @@ -2786,7 +2783,7 @@ module Impl { head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2825,20 +2822,21 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); /** Gets the tail of this access path, if any. */ abstract AccessPath getTail(); /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ - abstract predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail); + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2854,11 +2852,11 @@ module Impl { } private class AccessPathNil extends AccessPath, TAccessPathNil { - override TypedContent getHead() { none() } + override Content getHead() { none() } override AccessPath getTail() { none() } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } override AccessPathFrontNil getFront() { result = TFrontNil() } @@ -2870,21 +2868,21 @@ module Impl { } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head_; + private Content head_; private DataFlowType t; private AccessPath tail_; AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head_ } + override Content getHead() { result = head_ } override AccessPath getTail() { result = tail_ } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and typ = t and tail = tail_ } - override AccessPathFrontHead getFront() { result = TFrontHead(head_.getContent()) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { @@ -2905,16 +2903,16 @@ module Impl { or result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) or - exists(TypedContent tc2, TypedContent tc3, int len | tail_ = TAccessPathCons2(tc2, _, tc3, len) | - result = head_ + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true or - result = head_ + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - exists(TypedContent tc2, int len | tail_ = TAccessPathCons1(tc2, len) | - result = head_ + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head_ + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2926,14 +2924,14 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; + private Content head1; private DataFlowType t; - private TypedContent head2; + private Content head2; private int len; AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } override AccessPath getTail() { Stage5::consCand(head1, t, result.getApprox()) and @@ -2941,7 +2939,7 @@ module Impl { result.length() = len - 1 } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head1 and typ = t and Stage5::consCand(head1, t, tail.getApprox()) and @@ -2949,7 +2947,7 @@ module Impl { tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head1.getContent()) } + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { result = TConsCons(head1, t, head2, len) or @@ -2968,23 +2966,23 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head_; + private Content head_; private int len; AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head_ } + override Content getHead() { result = head_ } override AccessPath getTail() { Stage5::consCand(head_, _, result.getApprox()) and result.length() = len - 1 } - override predicate isCons(TypedContent head, DataFlowType typ, AccessPath tail) { + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and Stage5::consCand(head_, typ, tail.getApprox()) and tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head_.getContent()) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } @@ -3383,15 +3381,15 @@ module Impl { t = node.getDataFlowType() and ap = TAccessPathNil() or - exists(TypedContent tc, DataFlowType t0, AccessPath ap0 | - pathStoreStep(mid, node, state, t0, ap0, tc, t, cc) and - ap.isCons(tc, t0, ap0) and + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and sc = mid.getSummaryCtx() ) or - exists(TypedContent tc, AccessPath ap0 | - pathReadStep(mid, node, state, ap0, tc, cc) and - ap0.isCons(tc, t, ap) and + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and sc = mid.getSummaryCtx() ) or @@ -3404,22 +3402,22 @@ module Impl { pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, TypedContent tc, DataFlowType t, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, _, node, _, t) and + Stage5::storeStepCand(mid.getNodeEx(), _, _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3723,7 +3721,7 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) @@ -3731,7 +3729,7 @@ module Impl { fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) From b534e7b6d57b331504b783d4ca2223907124baa7 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 10:08:18 +0200 Subject: [PATCH 64/96] Dataflow: Remove superfluous columns --- .../java/dataflow/internal/DataFlowImpl.qll | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index cb1bef4e383..59ace9d0183 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -391,8 +391,8 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType) { - store(pragma[only_bind_into](node1.asNode()), tc, c, pragma[only_bind_into](node2.asNode()), + private predicate storeEx(NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType) { + store(pragma[only_bind_into](node1.asNode()), _, c, pragma[only_bind_into](node2.asNode()), contentType, containerType) and hasReadStep(c) and stepFilter(node1, node2) @@ -479,7 +479,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, _, node, _, _) + storeEx(mid, _, node, _, _) ) or // read @@ -575,7 +575,7 @@ module Impl { not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, _, c, node, _, _) + storeEx(mid, c, node, _, _) ) } @@ -712,7 +712,7 @@ module Impl { exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, _, c, mid, _, _) + storeEx(node, c, mid, _, _) ) } @@ -802,11 +802,11 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ) { revFlowIsReadAndStored(c) and revFlow(node2) and - storeEx(node1, tc, c, node2, contentType, containerType) and + storeEx(node1, c, node2, contentType, containerType) and exists(ap1) } @@ -1049,7 +1049,7 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1319,7 +1319,7 @@ module Impl { ) { exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, _, c, node2, contentType, containerType) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and t2 = getTyp(containerType) and typecheckStore(t1, contentType) ) @@ -1671,10 +1671,10 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType ) { exists(Ap ap2 | - PrevStage::storeStepCand(node1, _, tc, c, node2, contentType, containerType) and + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) @@ -2023,7 +2023,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, _, node, _, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2046,7 +2046,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, _, next, _, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -3417,7 +3417,7 @@ module Impl { ) { t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, _, c, node, _, t) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3624,7 +3624,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, _, n2, _, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -4283,7 +4283,7 @@ module Impl { midNode = mid.getNodeEx() and t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, _, c, node, contentType, t2) and + storeEx(midNode, c, node, contentType, t2) and ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and compatibleTypes(t1, contentType) @@ -4543,7 +4543,7 @@ module Impl { exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, _, c, midNode, _, _) and + storeEx(node, c, midNode, _, _) and ap.getHead() = c ) } From 5373b4d4661efa4e878dd454f334fb559b82d1b4 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 10:13:28 +0200 Subject: [PATCH 65/96] Dataflow: Remove superfluous predicates. --- .../java/dataflow/internal/DataFlowImpl.qll | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 59ace9d0183..9132c0ab563 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2521,9 +2521,6 @@ module Impl { } } - /** Gets the access path obtained by pushing `c` onto the `t,apa` pair. */ - private AccessPathApprox push(Content c, DataFlowType t, AccessPathApprox apa) { result.isCons(c, t, apa) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2551,7 +2548,7 @@ module Impl { Typ getTyp(DataFlowType t) { result = t } bindingset[c, t, tail] - Ap apCons(Content c, Typ t, Ap tail) { result = push(c, t, tail) } + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; @@ -2664,8 +2661,6 @@ module Impl { SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - ParamNodeEx getParamNode() { result = p } override string toString() { result = p + ": " + ap } @@ -2832,9 +2827,6 @@ module Impl { /** Gets the head of this access path, if any. */ abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); @@ -2854,8 +2846,6 @@ module Impl { private class AccessPathNil extends AccessPath, TAccessPathNil { override Content getHead() { none() } - override AccessPath getTail() { none() } - override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } override AccessPathFrontNil getFront() { result = TFrontNil() } @@ -2876,8 +2866,6 @@ module Impl { override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail_ } - override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and typ = t and tail = tail_ } @@ -2933,12 +2921,6 @@ module Impl { override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, t, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 - } - override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head1 and typ = t and @@ -2973,10 +2955,6 @@ module Impl { override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head_, _, result.getApprox()) and result.length() = len - 1 - } - override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and Stage5::consCand(head_, typ, tail.getApprox()) and tail.length() = len - 1 From 4f2d2361a47393b0b15dd7adc6a9f6f4f758719c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 28 Mar 2023 09:50:00 +0200 Subject: [PATCH 66/96] Dataflow: Eliminate TypedContent. --- .../java/dataflow/internal/DataFlowImpl.qll | 2 +- .../dataflow/internal/DataFlowImplCommon.qll | 47 +++---------------- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 9132c0ab563..8a3598bb076 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -392,7 +392,7 @@ module Impl { pragma[nomagic] private predicate storeEx(NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType) { - store(pragma[only_bind_into](node1.asNode()), _, c, pragma[only_bind_into](node2.asNode()), + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), contentType, containerType) and hasReadStep(c) and stepFilter(node1, node2) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 50ee53c4f78..330e59567f2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -815,26 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Content c, Node node2, DataFlowType contentType, DataFlowType containerType) { - tc.getContent() = c and - tc.getContainerType() = containerType and - store(node1, c, node2, contentType, containerType) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -934,9 +928,6 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - cached newtype TAccessPathFront = TFrontNil() or @@ -1415,30 +1406,6 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ From 9ad2da61962fafffa5bb7a1b519cb51732e034dd Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 10:27:26 +0200 Subject: [PATCH 67/96] Java: Fix reference to TypedContent. --- java/ql/src/utils/modelgenerator/internal/CaptureModels.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index f47ecf700ba..11bd2f32b58 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -139,9 +139,9 @@ module ThroughFlowConfig implements DataFlow::StateConfigSig { predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { - exists(DataFlowImplCommon::TypedContent tc | - DataFlowImplCommon::store(node1, tc, node2, _) and - isRelevantContent(tc.getContent()) and + exists(DataFlow::Content c | + DataFlowImplCommon::store(node1, c, node2, _, _) and + isRelevantContent(c) and ( state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1 or From a761eea2dc9d839b4970cee4ba1d56da5855532f Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 10:30:16 +0200 Subject: [PATCH 68/96] Dataflow: Autoformat --- .../java/dataflow/internal/DataFlowImpl.qll | 156 +++++++++++------- 1 file changed, 96 insertions(+), 60 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 8a3598bb076..2c29bc5c311 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -391,7 +391,9 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType) { + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), contentType, containerType) and hasReadStep(c) and @@ -802,7 +804,8 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { revFlowIsReadAndStored(c) and revFlow(node2) and @@ -1049,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1192,8 +1196,8 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and @@ -1202,7 +1206,8 @@ module Impl { pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } @@ -1210,8 +1215,8 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and @@ -1380,8 +1385,7 @@ module Impl { ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - TypOption::some(argT), + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and @@ -1392,20 +1396,24 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, TypOption argT, - ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1414,8 +1422,8 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, - ParamNodeEx p, Typ t, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, @@ -1445,14 +1453,14 @@ module Impl { DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and @@ -1469,8 +1477,10 @@ module Impl { exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1671,7 +1681,8 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { exists(Ap ap2 | PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and @@ -1774,9 +1785,8 @@ module Impl { conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and @@ -1898,7 +1908,9 @@ module Impl { Typ getTyp(DataFlowType t) { any() } bindingset[c, t, tail] - Ap apCons(Content c, Typ t, Ap tail) { result = true and exists(c) and exists(t) and exists(tail) } + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1919,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - Typ t, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -2355,7 +2367,8 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } @@ -2447,7 +2460,9 @@ module Impl { override AccessPathFront getFront() { result = TFrontHead(c) } - override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { head = c and typ = t and tail = TNil() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { @@ -2681,7 +2696,8 @@ module Impl { len = apa.len() and result = strictcount(DataFlowType t, AccessPathFront apf | - Stage5::consCand(c, t, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2756,7 +2772,8 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = @@ -2789,7 +2806,9 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and @@ -2957,7 +2976,8 @@ module Impl { override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { head = head_ and - Stage5::consCand(head_, typ, tail.getApprox()) and tail.length() = len - 1 + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head_) } @@ -3303,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3324,7 +3344,8 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and @@ -3373,7 +3394,10 @@ module Impl { or pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and t = mid.getType() and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } @@ -3391,7 +3415,8 @@ module Impl { pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { t0 = mid.getType() and ap0 = mid.getAp() and @@ -3515,8 +3540,8 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | pathNode(_, ret, state, cc, sc, t, ap, _) and @@ -3562,10 +3587,11 @@ module Impl { PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), + pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3619,7 +3645,9 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and @@ -3706,8 +3734,7 @@ module Impl { or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -4075,7 +4102,9 @@ module Impl { DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4097,7 +4126,8 @@ module Impl { override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getSummaryCtx4(), result.getType(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4269,13 +4299,16 @@ module Impl { } pragma[nomagic] - private predicate apConsFwd(DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2) { + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4315,7 +4348,8 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) @@ -4392,14 +4426,17 @@ module Impl { DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 | + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and @@ -4497,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and From 9140cbefc0c6b4b99109de38c2e3ddb85154f0f9 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Apr 2023 10:28:20 +0200 Subject: [PATCH 69/96] Dataflow: Sync. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- .../csharp/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- .../modelgenerator/internal/CaptureModels.qll | 6 +- .../go/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- .../dataflow/new/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../new/internal/DataFlowImplCommon.qll | 141 +- .../ruby/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- .../swift/dataflow/internal/DataFlowImpl.qll | 1203 +++++++++-------- .../dataflow/internal/DataFlowImplCommon.qll | 141 +- 15 files changed, 4504 insertions(+), 4910 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index f47ecf700ba..11bd2f32b58 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -139,9 +139,9 @@ module ThroughFlowConfig implements DataFlow::StateConfigSig { predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { - exists(DataFlowImplCommon::TypedContent tc | - DataFlowImplCommon::store(node1, tc, node2, _) and - isRelevantContent(tc.getContent()) and + exists(DataFlow::Content c | + DataFlowImplCommon::store(node1, c, node2, _, _) and + isRelevantContent(c) and ( state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1 or diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index cd8e992c980..2c29bc5c311 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -9,6 +9,7 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic private import codeql.util.Unit +private import codeql.util.Option import DataFlow /** @@ -390,10 +391,12 @@ module Impl { private predicate hasReadStep(Content c) { read(_, c, _) } pragma[nomagic] - private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent()) and + private predicate storeEx( + NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType + ) { + store(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode()), + contentType, containerType) and + hasReadStep(c) and stepFilter(node1, node2) } @@ -478,7 +481,7 @@ module Impl { exists(NodeEx mid | useFieldFlow() and fwdFlow(mid, cc) and - storeEx(mid, _, node, _) + storeEx(mid, _, node, _, _) ) or // read @@ -570,12 +573,11 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlowConsCand(Content c) { - exists(NodeEx mid, NodeEx node, TypedContent tc | + exists(NodeEx mid, NodeEx node | not fullBarrier(node) and useFieldFlow() and fwdFlow(mid, _) and - storeEx(mid, tc, node, _) and - c = tc.getContent() + storeEx(mid, c, node, _, _) ) } @@ -709,11 +711,10 @@ module Impl { pragma[nomagic] private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { - exists(NodeEx mid, TypedContent tc | + exists(NodeEx mid | revFlow(mid, toReturn) and fwdFlowConsCand(c) and - storeEx(node, tc, mid, _) and - c = tc.getContent() + storeEx(node, c, mid, _, _) ) } @@ -803,15 +804,13 @@ module Impl { pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Content c | - revFlowIsReadAndStored(c) and - revFlow(node2) and - storeEx(node1, tc, node2, contentType) and - c = tc.getContent() and - exists(ap1) - ) + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, c, node2, contentType, containerType) and + exists(ap1) } pragma[nomagic] @@ -1053,7 +1052,8 @@ module Impl { predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ); predicate readStepCand(NodeEx n1, Content c, NodeEx n2); @@ -1063,6 +1063,10 @@ module Impl { class ApApprox = PrevStage::Ap; signature module StageParam { + class Typ { + string toString(); + } + class Ap; class ApNil extends Ap; @@ -1070,10 +1074,10 @@ module Impl { bindingset[result, ap] ApApprox getApprox(Ap ap); - ApNil getApNil(NodeEx node); + Typ getTyp(DataFlowType t); - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail); /** * An approximation of `Content` that corresponds to the precision level of @@ -1120,7 +1124,7 @@ module Impl { bindingset[node2, state2] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + Typ t, LocalCc lcc ); predicate flowOutOfCall( @@ -1131,17 +1135,26 @@ module Impl { DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow ); - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap); + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap); - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType); } module Stage implements StageSig { import Param /* Begin: Stage logic. */ + private module TypOption = Option; + + private class TypOption = TypOption::Option; + + pragma[nomagic] + private Typ getNodeTyp(NodeEx node) { + PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) + } + pragma[nomagic] private predicate flowIntoCallApa( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa @@ -1183,97 +1196,102 @@ module Impl { */ pragma[nomagic] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and PrevStage::revFlow(node, state, apa) and - filter(node, state, ap) + filter(node, state, t, ap) } pragma[inline] additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _) } pragma[assume_small_delta] pragma[nomagic] private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap, ApApprox apa ) { sourceNode(node, state) and (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argT instanceof TypOption::None and argAp = apNone() and summaryCtx = TParamNodeNone() and - ap = getApNil(node) and + t = getNodeTyp(node) and + ap instanceof ApNil and apa = getApprox(ap) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + exists(NodeEx mid, FlowState state0, Typ t0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argT, argAp, t0, ap, apa) and localCc = getLocalCc(mid, cc) | localStep(mid, state0, node, state, true, _, localCc) and - ap = ap0 and - apa = apa0 + t = t0 or - localStep(mid, state0, node, state, false, ap, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + localStep(mid, state0, node, state, false, t, localCc) and + ap instanceof ApNil ) or exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + fwdFlow(mid, state, _, _, _, _, t, ap, apa) and jumpStepEx(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil) and + exists(NodeEx mid | + fwdFlow(mid, state, _, _, _, _, _, ap, apa) and additionalJumpStep(mid, node) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil) and + exists(NodeEx mid, FlowState state0 | + fwdFlow(mid, state0, _, _, _, _, _, ap, apa) and additionalJumpStateStep(mid, state0, node, state) and cc = ccNone() and summaryCtx = TParamNodeNone() and + argT instanceof TypOption::None and argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + t = getNodeTyp(node) and + ap instanceof ApNil ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and - ap = apCons(tc, ap0) and + exists(Content c, Typ t0, Ap ap0 | + fwdFlowStore(_, t0, ap0, c, t, node, state, cc, summaryCtx, argT, argAp) and + ap = apCons(c, t0, ap0) and apa = getApprox(ap) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and - fwdFlowConsCand(ap0, c, ap) and + exists(Typ t0, Ap ap0, Content c | + fwdFlowRead(t0, ap0, c, _, node, state, cc, summaryCtx, argT, argAp) and + fwdFlowConsCand(t0, ap0, c, t, ap) and apa = getApprox(ap) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and if PrevStage::parameterMayFlowThrough(node, apa) then ( summaryCtx = TParamNodeSome(node.asNode()) and + argT = TypOption::some(t) and argAp = apSome(ap) ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() + summaryCtx = TParamNodeNone() and argT instanceof TypOption::None and argAp = apNone() ) or // flow out of a callable @@ -1281,7 +1299,7 @@ module Impl { DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, DataFlowCallable inner | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and inner = ret.getEnclosingCallable() and cc = getCallContextReturn(inner, call, innercc) and @@ -1293,7 +1311,7 @@ module Impl { DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and if allowsFieldFlow = false then ap instanceof ApNil else any() ) @@ -1301,27 +1319,26 @@ module Impl { pragma[nomagic] private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + NodeEx node1, Typ t1, Ap ap1, Content c, Typ t2, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and - typecheckStore(ap1, contentType) + exists(DataFlowType contentType, DataFlowType containerType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t1, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, c, node2, contentType, containerType) and + t2 = getTyp(containerType) and + typecheckStore(t1, contentType) ) } /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. + * Holds if forward flow with access path `tail` and type `t1` reaches a + * store of `c` on a container of type `t2` resulting in access path + * `cons`. */ pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) + private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) { + fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and + cons = apCons(c, t1, tail) } pragma[nomagic] @@ -1338,11 +1355,11 @@ module Impl { pragma[nomagic] private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp + Typ t, Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp ) { exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and apc = getHeadContent(ap) and readStepCand0(node1, apc, c, node2) ) @@ -1351,10 +1368,10 @@ module Impl { pragma[nomagic] private predicate fwdFlowIn( DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa ) { exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1363,13 +1380,13 @@ module Impl { pragma[nomagic] private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, - ApApprox argApa, Ap ap, ApApprox apa + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Typ argT, Ap argAp, + ApApprox argApa, Typ t, Ap ap, ApApprox apa ) { exists(ReturnKindExt kind | fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), TypOption::some(argT), + pragma[only_bind_into](apSome(argAp)), t, ap, pragma[only_bind_into](apa)) and kind = ret.getKind() and parameterFlowThroughAllowed(summaryCtx, kind) and argApa = getApprox(argAp) and @@ -1380,19 +1397,23 @@ module Impl { pragma[inline] private predicate fwdFlowThrough0( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgT, innerArgAp, innerArgApa, t, + ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argT, argAp, innerSummaryCtx, innerArgT, + innerArgAp) } pragma[nomagic] private predicate fwdFlowThrough( DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, RetNodeEx ret, + ApApprox innerArgApa ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argT, argAp, t, ap, apa, ret, _, _, _, + innerArgApa) } /** @@ -1401,11 +1422,11 @@ module Impl { */ pragma[nomagic] private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, ParamNodeEx p, Typ t, Ap ap ) { exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t, ap, pragma[only_bind_into](apa)) and PrevStage::parameterMayFlowThrough(p, apa) and PrevStage::callMayFlowThroughRev(call) @@ -1413,33 +1434,36 @@ module Impl { } pragma[nomagic] - private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + private predicate storeStepFwd(NodeEx node1, Typ t1, Ap ap1, Content c, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, t1, ap1, c, _, node2, _, _, _, _, _) and + ap2 = apCons(c, t1, ap1) and + readStepFwd(_, ap2, c, _, _) } + pragma[nomagic] private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and - fwdFlowConsCand(ap1, c, ap2) + exists(Typ t1 | + fwdFlowRead(t1, ap1, c, n1, n2, _, _, _, _, _) and + fwdFlowConsCand(t1, ap1, c, _, ap2) + ) } pragma[nomagic] private predicate returnFlowsThrough0( DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ParamNodeEx innerSummaryCtx, Typ innerArgT, Ap innerArgAp, ApApprox innerArgApa ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa) + fwdFlowThrough0(call, _, state, ccc, _, _, _, _, ap, apa, ret, innerSummaryCtx, innerArgT, + innerArgAp, innerArgApa) } pragma[nomagic] private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Typ argT, + Ap argAp, Ap ap ) { exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argT, argAp, innerArgApa) and flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and pos = ret.getReturnPosition() and if allowsFieldFlow = false then ap instanceof ApNil else any() @@ -1450,11 +1474,13 @@ module Impl { private predicate flowThroughIntoCall( DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap ) { - exists(ApApprox argApa | + exists(ApApprox argApa, Typ argT | flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), allowsFieldFlow, argApa) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp), + argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argT), + pragma[only_bind_into](argAp), ap) and if allowsFieldFlow = false then argAp instanceof ApNil else any() ) } @@ -1465,7 +1491,7 @@ module Impl { ) { exists(ApApprox apa | flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and - fwdFlow(arg, _, _, _, _, ap, apa) + fwdFlow(arg, _, _, _, _, _, _, ap, apa) ) } @@ -1476,7 +1502,7 @@ module Impl { ) { exists(ApApprox apa | flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and - fwdFlow(ret, _, _, _, _, ap, apa) and + fwdFlow(ret, _, _, _, _, _, _, ap, apa) and pos = ret.getReturnPosition() ) } @@ -1494,14 +1520,14 @@ module Impl { NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { revFlow0(node, state, returnCtx, returnAp, ap) and - fwdFlow(node, state, _, _, _, ap) + fwdFlow(node, state, _, _, _, _, _, ap) } pragma[nomagic] private predicate revFlow0( NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap ) { - fwdFlow(node, state, _, _, _, ap) and + fwdFlow(node, state, _, _, _, _, _, ap) and sinkNode(node, state) and ( if hasSinkCallCtx() @@ -1516,10 +1542,9 @@ module Impl { revFlow(mid, state0, returnCtx, returnAp, ap) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and - revFlow(mid, state0, returnCtx, returnAp, nil) and + revFlow(mid, state0, returnCtx, returnAp, ap) and ap instanceof ApNil ) or @@ -1530,19 +1555,17 @@ module Impl { returnAp = apNone() ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid | additionalJumpStep(node, mid) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + revFlow(pragma[only_bind_into](mid), state, _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap) and + exists(NodeEx mid, FlowState state0 | additionalJumpStateStep(node, state, mid, state0) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, ap) and returnCtx = TReturnCtxNone() and returnAp = apNone() and ap instanceof ApNil @@ -1550,7 +1573,7 @@ module Impl { or // store exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowStore(ap0, c, ap, _, node, state, _, returnCtx, returnAp) and revFlowConsCand(ap0, c, ap) ) or @@ -1577,7 +1600,7 @@ module Impl { // flow out of a callable exists(ReturnPosition pos | revFlowOut(_, node, pos, state, _, _, ap) and - if returnFlowsThrough(node, pos, state, _, _, _, ap) + if returnFlowsThrough(node, pos, state, _, _, _, _, ap) then ( returnCtx = TReturnCtxMaybeFlowThrough(pos) and returnAp = apSome(ap) @@ -1589,12 +1612,11 @@ module Impl { pragma[nomagic] private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + Ap ap0, Content c, Ap ap, Typ t, NodeEx node, FlowState state, NodeEx mid, ReturnCtx returnCtx, ApOption returnAp ) { revFlow(mid, state, returnCtx, returnAp, ap0) and - storeStepFwd(node, ap, tc, mid, ap0) and - tc.getContent() = c + storeStepFwd(node, t, ap, c, mid, ap0) } /** @@ -1652,18 +1674,19 @@ module Impl { ) { exists(RetNodeEx ret, FlowState state, CcCall ccc | revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and matchesCall(ccc, call) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + NodeEx node1, Ap ap1, Content c, NodeEx node2, DataFlowType contentType, + DataFlowType containerType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + exists(Ap ap2 | + PrevStage::storeStepCand(node1, _, c, node2, contentType, containerType) and + revFlowStore(ap2, c, ap1, _, node1, _, node2, _, _) and revFlowConsCand(ap2, c, ap1) ) } @@ -1686,21 +1709,26 @@ module Impl { pragma[nomagic] predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } - private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + private predicate fwdConsCand(Content c, Typ t, Ap ap) { storeStepFwd(_, t, ap, c, _, _) } - private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + private predicate revConsCand(Content c, Typ t, Ap ap) { + exists(Ap ap2 | + revFlowStore(ap2, c, ap, t, _, _, _, _, _) and + revFlowConsCand(ap2, c, ap) + ) + } private predicate validAp(Ap ap) { revFlow(_, _, _, _, ap) and ap instanceof ApNil or - exists(TypedContent head, Ap tail | - consCand(head, tail) and - ap = apCons(head, tail) + exists(Content head, Typ t, Ap tail | + consCand(head, t, tail) and + ap = apCons(head, t, tail) ) } - additional predicate consCand(TypedContent tc, Ap ap) { - revConsCand(tc, ap) and + additional predicate consCand(Content c, Typ t, Ap ap) { + revConsCand(c, t, ap) and validAp(ap) } @@ -1715,7 +1743,7 @@ module Impl { pragma[nomagic] predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _) and + returnFlowsThrough(_, pos, _, _, p, _, ap, _) and parameterFlowsThroughRev(p, ap, pos, _) ) } @@ -1723,7 +1751,7 @@ module Impl { pragma[nomagic] predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + returnFlowsThrough(ret, pos, _, _, p, _, argAp, ap) and parameterFlowsThroughRev(p, argAp, pos, ap) and kind = pos.getKind() ) @@ -1752,19 +1780,18 @@ module Impl { boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and + fields = count(Content f0 | fwdConsCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap) - ) + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT, + ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap)) or fwd = false and nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and - fields = count(TypedContent f0 | consCand(f0, _)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + fields = count(Content f0 | consCand(f0, _, _)) and + conscand = count(Content f0, Typ t, Ap ap | consCand(f0, t, ap)) and states = count(FlowState state | revFlow(_, state, _, _, _)) and tuples = count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | @@ -1865,6 +1892,8 @@ module Impl { private module Stage2Param implements MkStage::StageParam { private module PrevStage = Stage1; + class Typ = Unit; + class Ap extends boolean { Ap() { this in [true, false] } } @@ -1876,10 +1905,12 @@ module Impl { bindingset[result, ap] PrevStage::Ap getApprox(Ap ap) { any() } - ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + Typ getTyp(DataFlowType t) { any() } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { + result = true and exists(c) and exists(t) and exists(tail) + } class ApHeadContent = Unit; @@ -1900,8 +1931,8 @@ module Impl { bindingset[node1, state1] bindingset[node2, state2] predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t, + LocalCc lcc ) { ( preservesValue = true and @@ -1915,7 +1946,7 @@ module Impl { preservesValue = false and additionalLocalStateStep(node1, state1, node2, state2) ) and - exists(ap) and + exists(t) and exists(lcc) } @@ -1932,9 +1963,10 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { PrevStage::revFlowState(state) and + exists(t) and exists(ap) and not stateBarrier(node, state) and ( @@ -1945,8 +1977,8 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage2 implements StageSig { @@ -2003,7 +2035,7 @@ module Impl { or node.asNode() instanceof OutNodeExt or - Stage2::storeStepCand(_, _, _, node, _) + Stage2::storeStepCand(_, _, _, node, _, _) or Stage2::readStepCand(_, _, node) or @@ -2026,7 +2058,7 @@ module Impl { additionalJumpStep(node, next) or flowIntoCallNodeCand2(_, node, next, _) or flowOutOfCallNodeCand2(_, node, _, next, _) or - Stage2::storeStepCand(node, _, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _, _) or Stage2::readStepCand(node, _, next) ) or @@ -2133,23 +2165,23 @@ module Impl { private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; + class Typ = DataFlowType; + class Ap = ApproxAccessPathFront; class ApNil = ApproxAccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getAHead() = c and exists(t) and exists(tail) } class ApHeadContent = ContentApprox; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } predicate projectToHeadContent = getContentApprox/1; @@ -2163,9 +2195,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and exists(lcc) } @@ -2179,17 +2211,17 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getAHead().getContent() + c = ap.getAHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2197,11 +2229,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2212,23 +2244,23 @@ module Impl { private module Stage4Param implements MkStage::StageParam { private module PrevStage = Stage3; + class Typ = DataFlowType; + class Ap = AccessPathFront; class ApNil = AccessPathFrontNil; PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.getHead() = c and exists(t) and exists(tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2243,9 +2275,9 @@ module Impl { pragma[nomagic] predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and exists(lcc) @@ -2289,7 +2321,7 @@ module Impl { } pragma[nomagic] - private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead()) } pragma[nomagic] private predicate expectsContentCand(NodeEx node, Ap ap) { @@ -2297,18 +2329,18 @@ module Impl { PrevStage::revFlow(node) and PrevStage::readStepCand(_, c, _) and expectsContentEx(node, c) and - c = ap.getHead().getContent() + c = ap.getHead() ) } pragma[nomagic] private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and not clear(node, ap) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and ( notExpectsContent(node) or @@ -2316,11 +2348,11 @@ module Impl { ) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { // We need to typecheck stores here, since reverse flow through a getter // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) + compatibleTypes(typ, contentType) } } @@ -2335,191 +2367,175 @@ module Impl { private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { exists(AccessPathFront apf | Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _, + apf) ) } /** - * Holds if a length 2 access path approximation with the head `tc` is expected + * Holds if a length 2 access path approximation with the head `c` is expected * to be expensive. */ - private predicate expensiveLen2unfolding(TypedContent tc) { + private predicate expensiveLen2unfolding(Content c) { exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + tails = strictcount(DataFlowType t, AccessPathFront apf | Stage4::consCand(c, t, apf)) and nodes = strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = c)) ) and accessPathApproxCostLimits(apLimit, tupleLimit) and apLimit < tails and tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() + not forceHighPrecision(c) ) } private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t)) and - not expensiveLen2unfolding(tc) + TNil() or + TConsNil(Content c, DataFlowType t) { + Stage4::consCand(c, t, TFrontNil()) and + not expensiveLen2unfolding(c) } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2)) and + TConsCons(Content c1, DataFlowType t, Content c2, int len) { + Stage4::consCand(c1, t, TFrontHead(c2)) and len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1) + not expensiveLen2unfolding(c1) } or - TCons1(TypedContent tc, int len) { + TCons1(Content c, int len) { len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc) + expensiveLen2unfolding(c) } /** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. + * Conceptually a list of `Content`s where nested tails are also paired with a + * `DataFlowType`, but only the first two elements of the list and its length + * are tracked. If data flows from a source to a given node with a given + * `AccessPathApprox`, this indicates the sequence of dereference operations + * needed to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ abstract private class AccessPathApprox extends TAccessPathApprox { abstract string toString(); - abstract TypedContent getHead(); + abstract Content getHead(); abstract int len(); - abstract DataFlowType getType(); - abstract AccessPathFront getFront(); - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail); } private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; + override string toString() { result = "" } - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } + override Content getHead() { none() } override int len() { result = 0 } - override DataFlowType getType() { result = t } + override AccessPathFront getFront() { result = TFrontNil() } - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { none() } } abstract private class AccessPathApproxCons extends AccessPathApprox { } private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; + private Content c; private DataFlowType t; - AccessPathApproxConsNil() { this = TConsNil(tc, t) } + AccessPathApproxConsNil() { this = TConsNil(c, t) } override string toString() { // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + result = "[" + c.toString() + "]" + concat(" : " + ppReprType(t)) } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = 1 } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and typ = t and tail = TNil() + } } private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; + private Content c1; + private DataFlowType t; + private Content c2; private int len; - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + AccessPathApproxConsCons() { this = TConsCons(c1, t, c2, len) } override string toString() { if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c1.toString() + ", " + c2.toString() + "]" + else result = "[" + c1.toString() + ", " + c2.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc1 } + override Content getHead() { result = c1 } override int len() { result = len } - override DataFlowType getType() { result = tc1.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c1) } - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c1 and + typ = t and ( - result = TConsCons(tc2, _, len - 1) + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) } } private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; + private Content c; private int len; - AccessPathApproxCons1() { this = TCons1(tc, len) } + AccessPathApproxCons1() { this = TCons1(c, len) } override string toString() { if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" } - override TypedContent getHead() { result = tc } + override Content getHead() { result = c } override int len() { result = len } - override DataFlowType getType() { result = tc.getContainerType() } + override AccessPathFront getFront() { result = TFrontHead(c) } - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and + override predicate isCons(Content head, DataFlowType typ, AccessPathApprox tail) { + head = c and ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | - result = TConsCons(tc2, _, len - 1) + exists(Content c2 | Stage4::consCand(c, typ, TFrontHead(c2)) | + tail = TConsCons(c2, _, _, len - 1) or len = 2 and - result = TConsNil(tc2, _) + tail = TConsNil(c2, _) or - result = TCons1(tc2, len - 1) + tail = TCons1(c2, len - 1) ) or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t)) and - result = TNil(t) - ) + len = 1 and + Stage4::consCand(c, typ, TFrontNil()) and + tail = TNil() ) } } - /** Gets the access path obtained by popping `tc` from `ap`, if any. */ - private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - - /** Gets the access path obtained by pushing `tc` onto `ap`. */ - private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - private newtype TAccessPathApproxOption = TAccessPathApproxNone() or TAccessPathApproxSome(AccessPathApprox apa) @@ -2535,6 +2551,8 @@ module Impl { private module Stage5Param implements MkStage::StageParam { private module PrevStage = Stage4; + class Typ = DataFlowType; + class Ap = AccessPathApprox; class ApNil = AccessPathApproxNil; @@ -2542,17 +2560,15 @@ module Impl { pragma[nomagic] PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } + Typ getTyp(DataFlowType t) { result = t } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + bindingset[c, t, tail] + Ap apCons(Content c, Typ t, Ap tail) { result.isCons(c, t, tail) } class ApHeadContent = Content; pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() } ApHeadContent projectToHeadContent(Content c) { result = c } @@ -2567,9 +2583,9 @@ module Impl { predicate localStep( NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, LocalCc lcc + DataFlowType t, LocalCc lcc ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) } @@ -2596,12 +2612,12 @@ module Impl { ) } - bindingset[node, state, ap] - predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + bindingset[node, state, t, ap] + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + bindingset[typ, contentType] + predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } } private module Stage5 = MkStage::Stage; @@ -2613,8 +2629,8 @@ module Impl { exists(AccessPathApprox apa0 | Stage5::parameterMayFlowThrough(p, _) and Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0) + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _, + TAccessPathApproxSome(apa), _, apa0) ) } @@ -2628,9 +2644,12 @@ module Impl { private newtype TSummaryCtx = TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - Stage5::parameterMayFlowThrough(p, ap.getApprox()) and - Stage5::revFlow(p, state, _) + TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) { + exists(AccessPathApprox apa | ap.getApprox() = apa | + Stage5::parameterMayFlowThrough(p, apa) and + Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and + Stage5::revFlow(p, state, _) + ) } /** @@ -2652,11 +2671,10 @@ module Impl { private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { private ParamNodeEx p; private FlowState s; + private DataFlowType t; private AccessPath ap; - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + SummaryCtxSome() { this = TSummaryCtxSome(p, s, t, ap) } ParamNodeEx getParamNode() { result = p } @@ -2673,12 +2691,13 @@ module Impl { * Gets the number of length 2 access path approximations that correspond to `apa`. */ private int count1to2unfold(AccessPathApproxCons1 apa) { - exists(TypedContent tc, int len | - tc = apa.getHead() and + exists(Content c, int len | + c = apa.getHead() and len = apa.len() and result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + strictcount(DataFlowType t, AccessPathFront apf | + Stage5::consCand(c, t, + any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) ) ) } @@ -2704,10 +2723,10 @@ module Impl { ) } - private AccessPathApprox getATail(AccessPathApprox apa) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result) + private predicate hasTail(AccessPathApprox apa, DataFlowType t, AccessPathApprox tail) { + exists(Content head | + apa.isCons(head, t, tail) and + Stage5::consCand(head, t, tail) ) } @@ -2716,7 +2735,7 @@ module Impl { * expected to be expensive. Holds with `unfold = true` otherwise. */ private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { - if apa.getHead().forceHighPrecision() + if forceHighPrecision(apa.getHead()) then unfold = true else exists(int aps, int nodes, int apLimit, int tupleLimit | @@ -2753,28 +2772,30 @@ module Impl { private int countPotentialAps(AccessPathApprox apa) { apa instanceof AccessPathApproxNil and result = 1 or - result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) + result = + strictsum(DataFlowType t, AccessPathApprox tail | hasTail(apa, t, tail) | countAps(tail)) } private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { + TAccessPathNil() or + TAccessPathCons(Content head, DataFlowType t, AccessPath tail) { exists(AccessPathApproxCons apa | not evalUnfold(apa, false) and head = apa.getHead() and - tail.getApprox() = getATail(apa) + hasTail(apa, t, tail.getApprox()) ) } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | + TAccessPathCons2(Content head1, DataFlowType t, Content head2, int len) { + exists(AccessPathApproxCons apa, AccessPathApprox tail | evalUnfold(apa, false) and not expensiveLen1to2unfolding(apa) and apa.len() = len and + hasTail(apa, t, tail) and head1 = apa.getHead() and - head2 = getATail(apa).getHead() + head2 = tail.getHead() ) } or - TAccessPathCons1(TypedContent head, int len) { + TAccessPathCons1(Content head, int len) { exists(AccessPathApproxCons apa | evalUnfold(apa, false) and expensiveLen1to2unfolding(apa) and @@ -2785,16 +2806,19 @@ module Impl { private newtype TPathNode = pragma[assume_small_delta] - TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap + ) { // A PathNode is introduced by a source ... Stage5::revFlow(node, state) and sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or // ... or a step from an existing PathNode to another node. - pathStep(_, node, state, cc, sc, ap) and + pathStep(_, node, state, cc, sc, t, ap) and Stage5::revFlow(node, state, ap.getApprox()) } or TPathNodeSink(NodeEx node, FlowState state) { @@ -2812,17 +2836,18 @@ module Impl { } /** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. + * A list of `Content`s where nested tails are also paired with a + * `DataFlowType`. If data flows from a source to a given node with a given + * `AccessPath`, this indicates the sequence of dereference operations needed + * to get from the value in the node to the tracked object. The + * `DataFlowType`s indicate the types of the stored values. */ private class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); + abstract Content getHead(); - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); + /** Holds if this is a representation of `head` followed by the `typ,tail` pair. */ + abstract predicate isCons(Content head, DataFlowType typ, AccessPath tail); /** Gets the front of this access path. */ abstract AccessPathFront getFront(); @@ -2835,80 +2860,66 @@ module Impl { /** Gets a textual representation of this access path. */ abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } } private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; + override Content getHead() { none() } - AccessPathNil() { this = TAccessPathNil(t) } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { none() } - DataFlowType getType() { result = t } + override AccessPathFrontNil getFront() { result = TFrontNil() } - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } + override AccessPathApproxNil getApprox() { result = TNil() } override int length() { result = 0 } - override string toString() { result = concat(": " + ppReprType(t)) } + override string toString() { result = "" } } private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; + private Content head_; + private DataFlowType t; + private AccessPath tail_; - AccessPathCons() { this = TAccessPathCons(head, tail) } + AccessPathCons() { this = TAccessPathCons(head_, t, tail_) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { result = tail } + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and typ = t and tail = tail_ + } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } pragma[assume_small_delta] override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) + result = TConsNil(head_, t) and tail_ = TAccessPathNil() or - result = TConsCons(head, tail.getHead(), this.length()) + result = TConsCons(head_, t, tail_.getHead(), this.length()) or - result = TCons1(head, this.length()) + result = TCons1(head_, this.length()) } pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } + override int length() { result = 1 + tail_.length() } private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) + tail_ = TAccessPathNil() and + needsSuffix = false and + result = head_.toString() + "]" + concat(" : " + ppReprType(t)) + or + result = head_ + ", " + tail_.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(Content c2, Content c3, int len | tail_ = TAccessPathCons2(c2, _, c3, len) | + result = head_ + ", " + c2 + ", " + c3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head_ + ", " + c2 + ", " + c3 + "]" and len = 2 and needsSuffix = false ) or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + exists(Content c2, int len | tail_ = TAccessPathCons1(c2, len) | + result = head_ + ", " + c2 + ", ... (" and len > 1 and needsSuffix = true or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + result = head_ + ", " + c2 + "]" and len = 1 and needsSuffix = false ) } @@ -2920,24 +2931,27 @@ module Impl { } private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; + private Content head1; + private DataFlowType t; + private Content head2; private int len; - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + AccessPathCons2() { this = TAccessPathCons2(head1, t, head2, len) } - override TypedContent getHead() { result = head1 } + override Content getHead() { result = head1 } - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox()) and - result.getHead() = head2 and - result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head1 and + typ = t and + Stage5::consCand(head1, t, tail.getApprox()) and + tail.getHead() = head2 and + tail.length() = len - 1 } override AccessPathFrontHead getFront() { result = TFrontHead(head1) } override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or + result = TConsCons(head1, t, head2, len) or result = TCons1(head1, len) } @@ -2953,27 +2967,29 @@ module Impl { } private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; + private Content head_; private int len; - AccessPathCons1() { this = TAccessPathCons1(head, len) } + AccessPathCons1() { this = TAccessPathCons1(head_, len) } - override TypedContent getHead() { result = head } + override Content getHead() { result = head_ } - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + override predicate isCons(Content head, DataFlowType typ, AccessPath tail) { + head = head_ and + Stage5::consCand(head_, typ, tail.getApprox()) and + tail.length() = len - 1 } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } + override AccessPathFrontHead getFront() { result = TFrontHead(head_) } - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + override AccessPathApproxCons getApprox() { result = TCons1(head_, len) } override int length() { result = len } override string toString() { if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + then result = "[" + head_.toString() + "]" + else result = "[" + head_.toString() + ", ... (" + len.toString() + ")]" } } @@ -3034,9 +3050,7 @@ module Impl { private string ppType() { this instanceof PathNodeSink and result = "" or - this.(PathNodeMid).getAp() instanceof AccessPathNil and result = "" - or - exists(DataFlowType t | t = this.(PathNodeMid).getAp().getHead().getContainerType() | + exists(DataFlowType t | t = this.(PathNodeMid).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -3177,9 +3191,10 @@ module Impl { FlowState state; CallContext cc; SummaryCtx sc; + DataFlowType t; AccessPath ap; - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) } override NodeEx getNodeEx() { result = node } @@ -3189,11 +3204,13 @@ module Impl { SummaryCtx getSummaryCtx() { result = sc } + DataFlowType getType() { result = t } + AccessPath getAp() { result = ap } private PathNodeMid getSuccMid() { pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) + result.getSummaryCtx(), result.getType(), result.getAp()) } override PathNodeImpl getASuccessorImpl() { @@ -3208,7 +3225,8 @@ module Impl { sourceNode(node, state) and sourceCallCtx(cc) and sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() } predicate isAtSink() { @@ -3305,8 +3323,8 @@ module Impl { } private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - LocalCallContext localCC + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap, LocalCallContext localCC ) { midnode = mid.getNodeEx() and state = mid.getState() and @@ -3315,6 +3333,7 @@ module Impl { localCC = getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), midnode.getEnclosingCallable()) and + t = mid.getType() and ap = mid.getAp() } @@ -3325,23 +3344,25 @@ module Impl { pragma[assume_small_delta] pragma[nomagic] private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, + AccessPath ap ) { exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) or - exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and - ap0 instanceof AccessPathNil + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, false, t, localCC) and + ap instanceof AccessPathNil ) or jumpStepEx(mid.getNodeEx(), node) and state = mid.getState() and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -3349,44 +3370,57 @@ module Impl { cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc instanceof SummaryCtxNone and mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TAccessPathNil() or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, DataFlowType t0, AccessPath ap0 | + pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and + ap.isCons(c, t0, ap0) and + sc = mid.getSummaryCtx() + ) or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() + exists(Content c, AccessPath ap0 | + pathReadStep(mid, node, state, ap0, c, cc) and + ap0.isCons(c, t, ap) and + sc = mid.getSummaryCtx() + ) or - pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + pathIntoCallable(mid, node, state, _, cc, sc, _) and t = mid.getType() and ap = mid.getAp() or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + pathOutOfCallable(mid, node, state, cc) and + t = mid.getType() and + ap = mid.getAp() and + sc instanceof SummaryCtxNone or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() + pathThroughCallable(mid, node, state, cc, t, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, Content c, CallContext cc ) { ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + c = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), c, node) and state = mid.getState() and cc = mid.getCallContext() } pragma[nomagic] private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc + PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, + DataFlowType t, CallContext cc ) { + t0 = mid.getType() and ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and state = mid.getState() and cc = mid.getCallContext() } @@ -3440,10 +3474,10 @@ module Impl { pragma[noinline] private predicate pathIntoArg( PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, _) and + pathNode(mid, arg, state, cc, _, t, ap, _) and arg.asNode().(ArgNode).argumentOf(call, apos) and apa = ap.getApprox() and parameterMatch(ppos, apos) @@ -3463,10 +3497,10 @@ module Impl { pragma[nomagic] private predicate pathIntoCallable0( PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, AccessPath ap ) { exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, t, ap, pragma[only_bind_into](apa)) and callable = resolveCall(call, outercc) and parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) @@ -3483,13 +3517,13 @@ module Impl { PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, SummaryCtx sc, DataFlowCall call ) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + exists(ParameterPosition pos, DataFlowCallable callable, DataFlowType t, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and ( - sc = TSummaryCtxSome(p, state, ap) + sc = TSummaryCtxSome(p, state, t, ap) or - not exists(TSummaryCtxSome(p, state, ap)) and + not exists(TSummaryCtxSome(p, state, t, ap)) and sc = TSummaryCtxNone() and // When the call contexts of source and sink needs to match then there's // never any reason to enter a callable except to find a summary. See also @@ -3506,11 +3540,11 @@ module Impl { /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t, + AccessPath ap, AccessPathApprox apa ) { exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, _) and + pathNode(_, ret, state, cc, sc, t, ap, _) and kind = ret.getKind() and apa = ap.getApprox() and parameterFlowThroughAllowed(sc.getParamNode(), kind) @@ -3521,11 +3555,11 @@ module Impl { pragma[nomagic] private predicate pathThroughCallable0( DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa + DataFlowType t, AccessPath ap, AccessPathApprox apa ) { exists(CallContext innercc, SummaryCtx sc | pathIntoCallable(mid, _, _, cc, innercc, sc, call) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa) + paramFlowsThrough(kind, state, innercc, sc, t, ap, apa) ) } @@ -3535,10 +3569,10 @@ module Impl { */ pragma[noinline] private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and out = getAnOutNodeFlow(kind, call, apa) ) } @@ -3551,11 +3585,12 @@ module Impl { pragma[nomagic] private predicate subpaths01( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t), + pragma[only_bind_into](apout)) and pathIntoCallable(arg, par, _, _, innercc, sc, _) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, pragma[only_bind_into](t), pragma[only_bind_into](apout), _) and not arg.isHidden() } @@ -3567,9 +3602,9 @@ module Impl { pragma[nomagic] private predicate subpaths02( PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout + NodeEx out, FlowState sout, DataFlowType t, AccessPath apout ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + subpaths01(arg, par, sc, innercc, kind, out, sout, t, apout) and out.asNode() = kind.getAnOutNode(_) } @@ -3579,11 +3614,11 @@ module Impl { pragma[nomagic] private predicate subpaths03( PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, - AccessPath apout + DataFlowType t, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, _) and + subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and + pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and kind = retnode.getKind() ) } @@ -3593,7 +3628,7 @@ module Impl { result.isHidden() and exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | localFlowBigStep(n1, _, n2, _, _, _, _) or - storeEx(n1, _, n2, _) or + storeEx(n1, _, n2, _, _) or readSetEx(n1, _, n2) ) } @@ -3610,12 +3645,14 @@ module Impl { * `ret -> out` is summarized as the edge `arg -> out`. */ predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + exists( + ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout, PathNodeMid out0 + | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, t, apout) and hasSuccessor(pragma[only_bind_into](arg), par, p) and not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _) + pathNode(out0, o, sout, _, _, t, apout, _) | out = out0 or out = out0.projectToSink() ) @@ -3690,15 +3727,14 @@ module Impl { ) { fwd = true and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = - count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + fields = count(Content f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and tuples = count(PathNode pn) @@ -3837,77 +3873,32 @@ module Impl { private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + TPartialNil() or + TPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } /** * Conceptually a list of `Content`s, but only the first * element of the list and its length are tracked. */ - private class RevPartialAccessPath extends TRevPartialAccessPath { + private class PartialAccessPath extends TPartialAccessPath { abstract string toString(); - Content getHead() { this = TRevPartialCons(result, _) } + Content getHead() { this = TPartialCons(result, _) } int len() { - this = TRevPartialNil() and result = 0 + this = TPartialNil() and result = 0 or - this = TRevPartialCons(_, result) + this = TPartialCons(_, result) } } - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { override string toString() { result = "" } } - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | + exists(Content c, int len | this = TPartialCons(c, len) | if len = 1 then result = "[" + c.toString() + "]" else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" @@ -3934,7 +3925,11 @@ module Impl { private newtype TSummaryCtx3 = TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + TSummaryCtx3Some(DataFlowType t) + + private newtype TSummaryCtx4 = + TSummaryCtx4None() or + TSummaryCtx4Some(PartialAccessPath ap) private newtype TRevSummaryCtx1 = TRevSummaryCtx1None() or @@ -3946,33 +3941,35 @@ module Impl { private newtype TRevSummaryCtx3 = TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + TRevSummaryCtx3Some(PartialAccessPath ap) private newtype TPartialPathNode = TPartialPathNodeFwd( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { sourceNode(node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and + sc4 = TSummaryCtx4None() and + t = node.getDataFlowType() and + ap = TPartialNil() and exists(explorationLimit()) or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and distSrc(node.getEnclosingCallable()) <= explorationLimit() } or TPartialPathNodeRev( NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap + PartialAccessPath ap ) { sinkNode(node, state) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and + ap = TPartialNil() and exists(explorationLimit()) or revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and @@ -3989,18 +3986,18 @@ module Impl { pragma[nomagic] private predicate partialPathNodeMk0( NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and not fullBarrier(node) and not stateBarrier(node, state) and - not clearsContentEx(node, ap.getHead().getContent()) and + not clearsContentEx(node, ap.getHead()) and ( notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) + expectsContentEx(node, ap.getHead()) ) and if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) + then compatibleTypes(node.getDataFlowType(), t) else any() } @@ -4060,11 +4057,7 @@ module Impl { private string ppType() { this instanceof PartialPathNodeRev and result = "" or - this.(PartialPathNodeFwd).getAp() instanceof PartialAccessPathNil and result = "" - or - exists(DataFlowType t | - t = this.(PartialPathNodeFwd).getAp().(PartialAccessPathCons).getType() - | + exists(DataFlowType t | t = this.(PartialPathNodeFwd).getType() | // The `concat` becomes "" if `ppReprType` has no result. result = concat(" : " + ppReprType(t)) ) @@ -4105,9 +4098,13 @@ module Impl { TSummaryCtx1 sc1; TSummaryCtx2 sc2; TSummaryCtx3 sc3; + TSummaryCtx4 sc4; + DataFlowType t; PartialAccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + PartialPathNodeFwd() { + this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, sc4, t, ap) + } NodeEx getNodeEx() { result = node } @@ -4121,11 +4118,16 @@ module Impl { TSummaryCtx3 getSummaryCtx3() { result = sc3 } + TSummaryCtx4 getSummaryCtx4() { result = sc4 } + + DataFlowType getType() { result = t } + PartialAccessPath getAp() { result = ap } override PartialPathNodeFwd getASuccessor() { partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), + result.getSummaryCtx4(), result.getType(), result.getAp()) } predicate isSource() { @@ -4134,6 +4136,7 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and ap instanceof TPartialNil } } @@ -4144,7 +4147,7 @@ module Impl { TRevSummaryCtx1 sc1; TRevSummaryCtx2 sc2; TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; + PartialAccessPath ap; PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } @@ -4158,7 +4161,7 @@ module Impl { TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - RevPartialAccessPath getAp() { result = ap } + PartialAccessPath getAp() { result = ap } override PartialPathNodeRev getASuccessor() { revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), @@ -4170,13 +4173,13 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + ap = TPartialNil() } } private predicate partialPathStep( PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and ( @@ -4186,6 +4189,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() or additionalLocalFlowStep(mid.getNodeEx(), node) and @@ -4194,16 +4199,20 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() ) or jumpStepEx(mid.getNodeEx(), node) and @@ -4212,6 +4221,8 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and + t = mid.getType() and ap = mid.getAp() or additionalJumpStep(mid.getNodeEx(), node) and @@ -4220,44 +4231,52 @@ module Impl { sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and cc instanceof CallContextAny and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() and mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) + t = node.getDataFlowType() and + ap = TPartialNil() or - partialPathStoreStep(mid, _, _, node, ap) and + partialPathStoreStep(mid, _, _, _, node, t, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc) and + exists(DataFlowType t0, PartialAccessPath ap0, Content c | + partialPathReadStep(mid, t0, ap0, c, node, cc) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0) + sc4 = mid.getSummaryCtx4() and + apConsFwd(t, ap, c, t0, ap0) ) or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, sc4, _, t, ap) or - partialPathOutOfCallable(mid, node, state, cc, ap) and + partialPathOutOfCallable(mid, node, state, cc, t, ap) and sc1 = TSummaryCtx1None() and sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() + sc3 = TSummaryCtx3None() and + sc4 = TSummaryCtx4None() or - partialPathThroughCallable(mid, node, state, cc, ap) and + partialPathThroughCallable(mid, node, state, cc, t, ap) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() } bindingset[result, i] @@ -4265,55 +4284,61 @@ module Impl { pragma[inline] private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, + DataFlowType t2, PartialAccessPath ap2 ) { exists(NodeEx midNode, DataFlowType contentType | midNode = mid.getNodeEx() and + t1 = mid.getType() and ap1 = mid.getAp() and - storeEx(midNode, tc, node, contentType) and - ap2.getHead() = tc and + storeEx(midNode, c, node, contentType, t2) and + ap2.getHead() = c and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + compatibleTypes(t1, contentType) ) } pragma[nomagic] - private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { - partialPathStoreStep(_, ap1, tc, _, ap2) + private predicate apConsFwd( + DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 + ) { + partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) } pragma[nomagic] private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, + CallContext cc ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and + t = mid.getType() and ap = mid.getAp() and - read(midNode, tc.getContent(), node) and - ap.getHead() = tc and + read(midNode, c, node) and + ap.getHead() = c and cc = mid.getCallContext() ) } private predicate partialPathOutOfCallable0( PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap + DataFlowType t, PartialAccessPath ap ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and + t = mid.getType() and ap = mid.getAp() } pragma[nomagic] private predicate partialPathOutOfCallable1( PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4323,10 +4348,11 @@ module Impl { } private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) | out.asNode() = kind.getAnOutNode(call) ) @@ -4335,13 +4361,14 @@ module Impl { pragma[noinline] private predicate partialPathIntoArg( PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap + DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ArgNode arg, ArgumentPosition apos | arg = mid.getNodeEx().asNode() and state = mid.getState() and cc = mid.getCallContext() and arg.argumentOf(call, apos) and + t = mid.getType() and ap = mid.getAp() and parameterMatch(ppos, apos) ) @@ -4350,23 +4377,24 @@ module Impl { pragma[nomagic] private predicate partialPathIntoCallable0( PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap + CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap) and + partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and callable = resolveCall(call, outercc) } private predicate partialPathIntoCallable( PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap + TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap ) { exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and p.isParameterOf(callable, pos) and sc1 = TSummaryCtx1Param(p) and sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + sc3 = TSummaryCtx3Some(t) and + sc4 = TSummaryCtx4Some(ap) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4377,7 +4405,7 @@ module Impl { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap + TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap ) { exists(PartialPathNodeFwd mid, RetNodeEx ret | mid.getNodeEx() = ret and @@ -4387,6 +4415,8 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + sc4 = mid.getSummaryCtx4() and + t = mid.getType() and ap = mid.getAp() ) } @@ -4394,19 +4424,22 @@ module Impl { pragma[noinline] private predicate partialPathThroughCallable0( DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, - CallContext cc, PartialAccessPath ap + CallContext cc, DataFlowType t, PartialAccessPath ap ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + exists( + CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4 + | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, sc4, call, _, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, sc4, t, ap) ) } private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, + PartialAccessPath ap ) { exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and out.asNode() = kind.getAnOutNode(call) ) } @@ -4414,7 +4447,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathStep( PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, - TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap ) { localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4428,15 +4461,15 @@ module Impl { sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or jumpStepEx(node, mid.getNodeEx()) and state = mid.getState() and @@ -4450,15 +4483,15 @@ module Impl { sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil() or revPartialPathReadStep(mid, _, _, node, ap) and state = mid.getState() and @@ -4466,7 +4499,7 @@ module Impl { sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() or - exists(RevPartialAccessPath ap0, Content c | + exists(PartialAccessPath ap0, Content c | revPartialPathStoreStep(mid, ap0, c, node) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and @@ -4501,8 +4534,7 @@ module Impl { pragma[inline] private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 + PartialPathNodeRev mid, PartialAccessPath ap1, Content c, NodeEx node, PartialAccessPath ap2 ) { exists(NodeEx midNode | midNode = mid.getNodeEx() and @@ -4514,27 +4546,26 @@ module Impl { } pragma[nomagic] - private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + private predicate apConsRev(PartialAccessPath ap1, Content c, PartialAccessPath ap2) { revPartialPathReadStep(_, ap1, c, _, ap2) } pragma[nomagic] private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + PartialPathNodeRev mid, PartialAccessPath ap, Content c, NodeEx node ) { - exists(NodeEx midNode, TypedContent tc | + exists(NodeEx midNode | midNode = mid.getNodeEx() and ap = mid.getAp() and - storeEx(node, tc, midNode, _) and - ap.getHead() = c and - tc.getContent() = c + storeEx(node, c, midNode, _, _) and + ap.getHead() = c ) } pragma[nomagic] private predicate revPartialPathIntoReturn( PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap ) { exists(NodeEx out | mid.getNodeEx() = out and @@ -4550,7 +4581,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathFlowsThrough( ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + TRevSummaryCtx3Some sc3, PartialAccessPath ap ) { exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | mid.getNodeEx() = p and @@ -4567,7 +4598,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable0( DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap + PartialAccessPath ap ) { exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and @@ -4577,7 +4608,7 @@ module Impl { pragma[nomagic] private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap ) { exists(DataFlowCall call, ArgumentPosition pos | revPartialPathThroughCallable0(call, mid, pos, state, ap) and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll index 648d5c2b073..330e59567f2 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll @@ -815,24 +815,20 @@ private module Cached { ) } - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - /** * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. + * `c`. * * This includes reverse steps through reads when the result of the read has * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) + predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { + exists(ContentSet cs | + c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) + ) } /** @@ -932,36 +928,15 @@ private module Cached { TReturnCtxNoFlowThrough() or TReturnCtxMaybeFlowThrough(ReturnPosition pos) - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - cached newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) + TFrontNil() or + TFrontHead(Content c) cached newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) + TApproxFrontNil() or + TApproxFrontHead(ContentApprox c) cached newtype TAccessPathFrontOption = @@ -1387,67 +1362,37 @@ class ReturnCtx extends TReturnCtx { } } -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - /** * The front of an approximated access path. This is either a head or a nil. */ abstract class ApproxAccessPathFront extends TApproxAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract boolean toBoolNonEmpty(); - TypedContentApprox getHead() { this = TApproxFrontHead(result) } + ContentApprox getHead() { this = TApproxFrontHead(result) } pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | + Content getAHead() { + exists(ContentApprox cont | this = TApproxFrontHead(cont) and - result = cont.getATypedContent() + cont = getContentApprox(result) ) } } class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } + override string toString() { result = "nil" } override boolean toBoolNonEmpty() { result = false } } class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; + private ContentApprox c; - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } + ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) } - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } + override string toString() { result = c.toString() } override boolean toBoolNonEmpty() { result = true } } @@ -1461,65 +1406,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { } } -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - /** * The front of an access path. This is either a head or a nil. */ abstract class AccessPathFront extends TAccessPathFront { abstract string toString(); - abstract DataFlowType getType(); - abstract ApproxAccessPathFront toApprox(); - TypedContent getHead() { this = TFrontHead(result) } + Content getHead() { this = TFrontHead(result) } } class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; + override string toString() { result = "nil" } - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } + override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() } } class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; + private Content c; - AccessPathFrontHead() { this = TFrontHead(tc) } + AccessPathFrontHead() { this = TFrontHead(c) } - override string toString() { result = tc.toString() } + override string toString() { result = c.toString() } - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } + override ApproxAccessPathFront toApprox() { result.getAHead() = c } } /** An optional access path front. */ From 71ae0909d8dd039e55bf2711dfb7f4f6c031bfcd Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 27 Apr 2023 14:32:12 +0200 Subject: [PATCH 70/96] Dataflow: Enforce type pruning in all forward stages. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../csharp/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../go/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../java/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../dataflow/new/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../ruby/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- .../swift/dataflow/internal/DataFlowImpl.qll | 36 +++++++++++-------- 8 files changed, 168 insertions(+), 120 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 2c29bc5c311..ddf98ac0f2f 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -2162,6 +2162,9 @@ module Impl { private import LocalFlowBigStep + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private module Stage3Param implements MkStage::StageParam { private module PrevStage = Stage2; @@ -2215,9 +2218,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2333,9 +2333,6 @@ module Impl { ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - bindingset[node, state, t, ap] predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { exists(state) and @@ -2613,11 +2610,16 @@ module Impl { } bindingset[node, state, t, ap] - predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { any() } + predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) { + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and + exists(state) and + exists(ap) + } - // Type checking is not necessary here as it has already been done in stage 3. bindingset[typ, contentType] - predicate typecheckStore(Typ typ, DataFlowType contentType) { any() } + predicate typecheckStore(Typ typ, DataFlowType contentType) { + compatibleTypes(typ, contentType) + } } private module Stage5 = MkStage::Stage; @@ -2819,7 +2821,8 @@ module Impl { or // ... or a step from an existing PathNode to another node. pathStep(_, node, state, cc, sc, t, ap) and - Stage5::revFlow(node, state, ap.getApprox()) + Stage5::revFlow(node, state, ap.getApprox()) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) } or TPathNodeSink(NodeEx node, FlowState state) { exists(PathNodeMid sink | @@ -3418,11 +3421,14 @@ module Impl { PathNodeMid mid, NodeEx node, FlowState state, DataFlowType t0, AccessPath ap0, Content c, DataFlowType t, CallContext cc ) { - t0 = mid.getType() and - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, c, node, _, t) and - state = mid.getState() and - cc = mid.getCallContext() + exists(DataFlowType contentType | + t0 = mid.getType() and + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, c, node, contentType, t) and + state = mid.getState() and + cc = mid.getCallContext() and + compatibleTypes(t0, contentType) + ) } private predicate pathOutOfCallable0( From 72b082806beaadb20462fd26b977d962125570f7 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Thu, 27 Apr 2023 16:36:55 +0100 Subject: [PATCH 71/96] Go: Update `html-template-escaping-passthrough` Modify this query to apply sanitizers only in the data flow between untrusted inputs and passthrough conversion types. --- .../CWE-79/HTMLTemplateEscapingPassthrough.ql | 10 +- .../HTMLTemplateEscapingPassthrough.expected | 178 ------------------ 2 files changed, 5 insertions(+), 183 deletions(-) diff --git a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql index fd5fccacbc6..d074f93baaf 100644 --- a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql +++ b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql @@ -64,6 +64,10 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co } override predicate isSink(DataFlow::Node sink) { isSinkToPassthroughType(sink, dstTypeName) } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof SharedXss::Sanitizer or sanitizer.getType() instanceof NumericType + } } /** @@ -100,7 +104,7 @@ class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTrac PassthroughTypeName getDstTypeName() { result = dstTypeName } override predicate isSource(DataFlow::Node source) { - isSourceConversionToPassthroughType(source, _) + isSourceConversionToPassthroughType(source, dstTypeName) } private predicate isSourceConversionToPassthroughType( @@ -141,10 +145,6 @@ class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Config override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource } override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof SharedXss::Sanitizer or sanitizer.getType() instanceof NumericType - } } /** diff --git a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected index 8c5673db6a4..e2e8e79ad26 100644 --- a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected +++ b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected @@ -1,92 +1,38 @@ edges | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | | HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | @@ -95,39 +41,16 @@ edges | HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | | HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | | HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | nodes | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | @@ -135,18 +58,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | @@ -154,18 +65,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | @@ -173,18 +72,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | @@ -192,18 +79,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | @@ -211,18 +86,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | @@ -230,18 +93,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | @@ -249,18 +100,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | @@ -268,12 +107,6 @@ nodes | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | | HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | semmle.label | escaped | | HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | semmle.label | call to UserAgent | @@ -283,21 +116,10 @@ nodes | HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | semmle.label | call to UserAgent | | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | | HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | semmle.label | call to HTMLEscapeString | | HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | semmle.label | src | | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | subpaths #select | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted | From b3669b818bde27ddefc3dcf69cc78994a903a713 Mon Sep 17 00:00:00 2001 From: amammad Date: Fri, 28 Apr 2023 04:56:47 +0200 Subject: [PATCH 72/96] v1.3 change name according to camelCase --- .../src/experimental/Security/CWE-074/paramiko/paramiko.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql index d296704b2d4..671bc0998fd 100644 --- a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql +++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql @@ -22,8 +22,8 @@ private API::Node paramikoClient() { result = API::moduleImport("paramiko").getMember("SSHClient").getReturn() } -class ParamikoCMDInjectionConfiguration extends TaintTracking::Configuration { - ParamikoCMDInjectionConfiguration() { this = "ParamikoCMDInjectionConfiguration" } +class ParamikoCmdInjectionConfiguration extends TaintTracking::Configuration { + ParamikoCmdInjectionConfiguration() { this = "ParamikoCMDInjectionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -51,7 +51,7 @@ class ParamikoCMDInjectionConfiguration extends TaintTracking::Configuration { } } -from ParamikoCMDInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink +from ParamikoCmdInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select sink.getNode(), source, sink, "This code execution depends on a $@.", source.getNode(), "a user-provided value" From 933b55d37d5a4d6a9ded3100cb81830f6c5bff60 Mon Sep 17 00:00:00 2001 From: tyage Date: Fri, 28 Apr 2023 15:49:26 +0900 Subject: [PATCH 73/96] Track interfile useRouter --- .../ql/lib/semmle/javascript/frameworks/Next.qll | 2 +- .../Security/CWE-079/DomBasedXss/Xss.expected | 16 ++++++++++++++++ .../XssWithAdditionalSources.expected | 15 +++++++++++++++ .../CWE-079/DomBasedXss/react-use-router-lib.js | 2 ++ .../CWE-079/DomBasedXss/react-use-router.js | 12 ++++++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router-lib.js diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll index c911757ef17..5ed808456d3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll @@ -248,7 +248,7 @@ module NextJS { * Gets a reference to a [Next.js router](https://nextjs.org/docs/api-reference/next/router). */ DataFlow::SourceNode nextRouter() { - result = DataFlow::moduleMember("next/router", "useRouter").getACall() + result = API::moduleImport("next/router").getMember("useRouter").getACall() or result = API::moduleImport("next/router") diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected index 5f6c8b305af..f0ac4a5ec87 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected @@ -579,6 +579,13 @@ nodes | react-use-router.js:23:43:23:54 | router.query | | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:61 | router.query.foobar | +| react-use-router.js:29:9:29:30 | router | +| react-use-router.js:29:18:29:30 | myUseRouter() | +| react-use-router.js:33:21:33:26 | router | +| react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:39 | router.query.foobar | | react-use-state.js:4:9:4:49 | state | | react-use-state.js:4:9:4:49 | state | | react-use-state.js:4:10:4:14 | state | @@ -1749,6 +1756,14 @@ edges | react-use-router.js:23:43:23:54 | router.query | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:54 | router.query | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:61 | router.query.foobar | react-use-router.js:22:17:22:22 | router | +| react-use-router.js:29:9:29:30 | router | react-use-router.js:33:21:33:26 | router | +| react-use-router.js:29:18:29:30 | myUseRouter() | react-use-router.js:29:9:29:30 | router | +| react-use-router.js:33:21:33:26 | router | react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:39 | router.query.foobar | react-use-router.js:29:18:29:30 | myUseRouter() | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | @@ -2447,6 +2462,7 @@ edges | react-use-router.js:11:24:11:42 | router.query.foobar | react-use-router.js:8:21:8:32 | router.query | react-use-router.js:11:24:11:42 | router.query.foobar | Cross-site scripting vulnerability due to $@. | react-use-router.js:8:21:8:32 | router.query | user-provided value | | react-use-router.js:11:24:11:42 | router.query.foobar | react-use-router.js:11:24:11:35 | router.query | react-use-router.js:11:24:11:42 | router.query.foobar | Cross-site scripting vulnerability due to $@. | react-use-router.js:11:24:11:35 | router.query | user-provided value | | react-use-router.js:23:43:23:61 | router.query.foobar | react-use-router.js:23:43:23:54 | router.query | react-use-router.js:23:43:23:61 | router.query.foobar | Cross-site scripting vulnerability due to $@. | react-use-router.js:23:43:23:54 | router.query | user-provided value | +| react-use-router.js:33:21:33:39 | router.query.foobar | react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | Cross-site scripting vulnerability due to $@. | react-use-router.js:33:21:33:32 | router.query | user-provided value | | react-use-state.js:5:51:5:55 | state | react-use-state.js:4:38:4:48 | window.name | react-use-state.js:5:51:5:55 | state | Cross-site scripting vulnerability due to $@. | react-use-state.js:4:38:4:48 | window.name | user-provided value | | react-use-state.js:11:51:11:55 | state | react-use-state.js:10:14:10:24 | window.name | react-use-state.js:11:51:11:55 | state | Cross-site scripting vulnerability due to $@. | react-use-state.js:10:14:10:24 | window.name | user-provided value | | react-use-state.js:17:51:17:55 | state | react-use-state.js:16:20:16:30 | window.name | react-use-state.js:17:51:17:55 | state | Cross-site scripting vulnerability due to $@. | react-use-state.js:16:20:16:30 | window.name | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 5d744fb9580..3edc5412c5b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -591,6 +591,13 @@ nodes | react-use-router.js:23:43:23:54 | router.query | | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:61 | router.query.foobar | +| react-use-router.js:29:9:29:30 | router | +| react-use-router.js:29:18:29:30 | myUseRouter() | +| react-use-router.js:33:21:33:26 | router | +| react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:39 | router.query.foobar | | react-use-state.js:4:9:4:49 | state | | react-use-state.js:4:9:4:49 | state | | react-use-state.js:4:10:4:14 | state | @@ -1811,6 +1818,14 @@ edges | react-use-router.js:23:43:23:54 | router.query | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:54 | router.query | react-use-router.js:23:43:23:61 | router.query.foobar | | react-use-router.js:23:43:23:61 | router.query.foobar | react-use-router.js:22:17:22:22 | router | +| react-use-router.js:29:9:29:30 | router | react-use-router.js:33:21:33:26 | router | +| react-use-router.js:29:18:29:30 | myUseRouter() | react-use-router.js:29:9:29:30 | router | +| react-use-router.js:33:21:33:26 | router | react-use-router.js:33:21:33:32 | router.query | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:32 | router.query | react-use-router.js:33:21:33:39 | router.query.foobar | +| react-use-router.js:33:21:33:39 | router.query.foobar | react-use-router.js:29:18:29:30 | myUseRouter() | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | | react-use-state.js:4:9:4:49 | state | react-use-state.js:5:51:5:55 | state | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router-lib.js b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router-lib.js new file mode 100644 index 00000000000..66c573cd8f8 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router-lib.js @@ -0,0 +1,2 @@ +import { useRouter } from "next/router"; +export let myUseRouter = useRouter; diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router.js b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router.js index 321821cd729..49d66634e5a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/react-use-router.js @@ -23,3 +23,15 @@ function Page({ router }) { return router.push(router.query.foobar)}>Click to XSS 3 // NOT OK } export const pageWithRouter = withRouter(Page); + +import { myUseRouter } from './react-use-router-lib'; +export function nextRouterWithLib() { + const router = myUseRouter() + return ( +
    + { + router.push(router.query.foobar) // NOT OK + }}>Click to XSS 1 +
    + ) +} From 3eca60cc4081b65f7ca8724ef7caa6a900c55c16 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:23:36 +0100 Subject: [PATCH 74/96] C++: Add static local testcases. --- .../dataflow-consistency.expected | 10 +++ .../dataflow/dataflow-tests/test.cpp | 64 ++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index 0750c1af392..e913ac5e0fa 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -115,6 +115,16 @@ postWithInFlow | test.cpp:602:3:602:7 | access to array [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:608:3:608:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:608:4:608:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:639:3:639:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:646:3:646:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:652:3:652:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:653:3:653:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:659:3:659:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:660:3:660:3 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:671:3:671:3 | s [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition uniqueParameterNodePosition diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 36b78896179..3e846882b0d 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -627,4 +627,66 @@ void test_def_via_phi_read(bool b) } intPointerSource(buffer); sink(buffer); // $ ast,ir -} \ No newline at end of file +} + +void test_static_local_1() { + static int x = source(); + sink(x); // $ ast,ir +} + +void test_static_local_2() { + static int x = source(); + x = 0; + sink(x); // clean +} + +void test_static_local_3() { + static int x = 0; + sink(x); // $ MISSING: ast, ir + x = source(); +} + +void test_static_local_4() { + static int x = 0; + sink(x); // clean + x = source(); + x = 0; +} + +void test_static_local_5() { + static int x = 0; + sink(x); // $ MISSING: ast,ir + x = 0; + x = source(); +} + +void test_static_local_6() { + static int s = source(); + static int* ptr_to_s = &s; + sink(*ptr_to_s); // $ MISSING: ast,ir +} + +void test_static_local_7() { + static int s = source(); + s = 0; + static int* ptr_to_s = &s; + sink(*ptr_to_s); // clean +} + +void test_static_local_8() { + static int s; + static int* ptr_to_s = &s; + sink(*ptr_to_s); // $ MISSING: ast,ir + + s = source(); +} + +void test_static_local_9() { + static int s; + static int* ptr_to_s = &s; + sink(*ptr_to_s); // clean + + s = source(); + s = 0; +} + From ee7b137c243feefce9d1098672df792060ea2c9f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:24:57 +0100 Subject: [PATCH 75/96] C++: Add dataflow for static locals. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 10 +++++++++- .../cpp/ir/dataflow/internal/SsaInternals.qll | 18 +++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 6d17e85863f..efd33b82a89 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -607,13 +607,21 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { result.getReturnKind() = kind } +/** A variable that behaves like a global variable. */ +class GlobalLikeVariable extends Variable { + GlobalLikeVariable() { + this instanceof Cpp::GlobalOrNamespaceVariable or + this instanceof Cpp::StaticLocalVariable + } +} + /** * Holds if data can flow from `node1` to `node2` in a way that loses the * calling context. For example, this would happen with flow through a * global or static variable. */ predicate jumpStep(Node n1, Node n2) { - exists(Cpp::GlobalOrNamespaceVariable v | + exists(GlobalLikeVariable v | exists(Ssa::GlobalUse globalUse | v = globalUse.getVariable() and n1.(FinalGlobalValue).getGlobalUse() = globalUse diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index ee958431b69..f2f32d09817 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -145,14 +145,14 @@ private newtype TDefOrUseImpl = or // Since the pruning stage doesn't know about global variables we can't use the above check to // rule out dead assignments to globals. - base.(VariableAddressInstruction).getAstVariable() instanceof Cpp::GlobalOrNamespaceVariable + base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable ) } or TUseImpl(Operand operand, int indirectionIndex) { isUse(_, operand, _, _, indirectionIndex) and not isDef(_, _, operand, _, _, _) } or - TGlobalUse(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) { + TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) { // Represents a final "use" of a global variable to ensure that // the assignment to a global variable isn't ruled out as dead. exists(VariableAddressInstruction vai, int defIndex | @@ -162,7 +162,7 @@ private newtype TDefOrUseImpl = indirectionIndex = [0 .. defIndex] + 1 ) } or - TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) { + TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) { // Represents the initial "definition" of a global variable when entering // a function body. exists(VariableAddressInstruction vai | @@ -458,7 +458,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse { } class GlobalUse extends UseImpl, TGlobalUse { - Cpp::GlobalOrNamespaceVariable global; + GlobalLikeVariable global; IRFunction f; GlobalUse() { this = TGlobalUse(global, f, ind) } @@ -468,7 +468,7 @@ class GlobalUse extends UseImpl, TGlobalUse { override int getIndirection() { result = ind + 1 } /** Gets the global variable associated with this use. */ - Cpp::GlobalOrNamespaceVariable getVariable() { result = global } + GlobalLikeVariable getVariable() { result = global } /** Gets the `IRFunction` whose body is exited from after this use. */ IRFunction getIRFunction() { result = f } @@ -496,14 +496,14 @@ class GlobalUse extends UseImpl, TGlobalUse { } class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl { - Cpp::GlobalOrNamespaceVariable global; + GlobalLikeVariable global; IRFunction f; int indirectionIndex; GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) } /** Gets the global variable associated with this definition. */ - Cpp::GlobalOrNamespaceVariable getVariable() { result = global } + GlobalLikeVariable getVariable() { result = global } /** Gets the `IRFunction` whose body is evaluated after this definition. */ IRFunction getIRFunction() { result = f } @@ -760,7 +760,7 @@ private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) { } private predicate sourceVariableIsGlobal( - SourceVariable sv, Cpp::GlobalOrNamespaceVariable global, IRFunction func, int indirectionIndex + SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex ) { exists(IRVariable irVar, BaseIRVariable base | sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and @@ -919,7 +919,7 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse { IRFunction getIRFunction() { result = global.getIRFunction() } /** Gets the global variable associated with this definition. */ - Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() } + GlobalLikeVariable getVariable() { result = global.getVariable() } } class Phi extends TPhi, SsaDefOrUse { From 24d1cac9d78b6c8189efcc04d286760307fb037c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:25:07 +0100 Subject: [PATCH 76/96] C++: Accept test changes. --- .../dataflow-tests/dataflow-ir-consistency.expected | 8 ++++++++ .../test/library-tests/dataflow/dataflow-tests/test.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index aac44e507c1..e0e7042d6b1 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -4,6 +4,14 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString +| test.cpp:632:6:632:24 | Use of x indirection | Node should have one toString but has 2. | +| test.cpp:632:6:632:24 | Use of x#init indirection | Node should have one toString but has 2. | +| test.cpp:637:6:637:24 | Use of x indirection | Node should have one toString but has 2. | +| test.cpp:637:6:637:24 | Use of x#init indirection | Node should have one toString but has 2. | +| test.cpp:663:6:663:24 | Use of s indirection | Node should have one toString but has 2. | +| test.cpp:663:6:663:24 | Use of s#init indirection | Node should have one toString but has 2. | +| test.cpp:669:6:669:24 | Use of s indirection | Node should have one toString but has 2. | +| test.cpp:669:6:669:24 | Use of s#init indirection | Node should have one toString but has 2. | missingToString parameterCallable localFlowIsLocal diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 3e846882b0d..5fae604f4d9 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -642,7 +642,7 @@ void test_static_local_2() { void test_static_local_3() { static int x = 0; - sink(x); // $ MISSING: ast, ir + sink(x); // $ ir MISSING: ast x = source(); } @@ -655,7 +655,7 @@ void test_static_local_4() { void test_static_local_5() { static int x = 0; - sink(x); // $ MISSING: ast,ir + sink(x); // $ ir MISSING: ast x = 0; x = source(); } @@ -663,7 +663,7 @@ void test_static_local_5() { void test_static_local_6() { static int s = source(); static int* ptr_to_s = &s; - sink(*ptr_to_s); // $ MISSING: ast,ir + sink(*ptr_to_s); // $ ir MISSING: ast } void test_static_local_7() { @@ -676,7 +676,7 @@ void test_static_local_7() { void test_static_local_8() { static int s; static int* ptr_to_s = &s; - sink(*ptr_to_s); // $ MISSING: ast,ir + sink(*ptr_to_s); // $ ir MISSING: ast s = source(); } From fd2f0257b6ab10f661be97576d270995597439a5 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:00:45 +0100 Subject: [PATCH 77/96] C++: Accept query changes. --- .../Format/NonConstantFormat/NonConstantFormat.expected | 1 + .../query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected index 0ea73248a7d..dde3d703fc4 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected @@ -3,6 +3,7 @@ | nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. | | nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. | | nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. | +| test.cpp:51:10:51:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:57:12:57:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:60:12:60:21 | call to const_wash | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:61:12:61:26 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp index 75c02296d7e..f42d6835aa7 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp @@ -48,7 +48,7 @@ int main(int argc, char **argv) { printf(choose_message(argc - 1), argc - 1); // GOOD printf(messages[1]); // GOOD printf(message); // GOOD - printf(make_message(argc - 1)); // BAD [NOT DETECTED] + printf(make_message(argc - 1)); // BAD printf("Hello, World\n"); // GOOD printf(_("Hello, World\n")); // GOOD { From c35cb70c9f4e9e767770a67c27c63d67959b2f37 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:40:18 +0100 Subject: [PATCH 78/96] C++: Fix inconsistencies. --- .../semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll | 3 ++- .../dataflow-tests/dataflow-ir-consistency.expected | 8 -------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index f2f32d09817..a1cfa44bb8e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -766,7 +766,8 @@ private predicate sourceVariableIsGlobal( sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and irVar = base.getIRVariable() and irVar.getEnclosingIRFunction() = func and - global = irVar.getAst() + global = irVar.getAst() and + not irVar instanceof IRDynamicInitializationFlag ) } diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index e0e7042d6b1..aac44e507c1 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -4,14 +4,6 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString -| test.cpp:632:6:632:24 | Use of x indirection | Node should have one toString but has 2. | -| test.cpp:632:6:632:24 | Use of x#init indirection | Node should have one toString but has 2. | -| test.cpp:637:6:637:24 | Use of x indirection | Node should have one toString but has 2. | -| test.cpp:637:6:637:24 | Use of x#init indirection | Node should have one toString but has 2. | -| test.cpp:663:6:663:24 | Use of s indirection | Node should have one toString but has 2. | -| test.cpp:663:6:663:24 | Use of s#init indirection | Node should have one toString but has 2. | -| test.cpp:669:6:669:24 | Use of s indirection | Node should have one toString but has 2. | -| test.cpp:669:6:669:24 | Use of s#init indirection | Node should have one toString but has 2. | missingToString parameterCallable localFlowIsLocal From 2716c73f870a1f8afc3c5129b8c896e8ca698db8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 10:49:49 +0100 Subject: [PATCH 79/96] C++: Add change note. --- cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md diff --git a/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md b/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md new file mode 100644 index 00000000000..3c7069f7050 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now supports tracking flow through static local variables. From 5a44fae515241d68a7a8d727f803c0b84a6f74ae Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Fri, 28 Apr 2023 10:56:12 +0100 Subject: [PATCH 80/96] Go: add test for unrelated A->C data flow --- .../HTMLTemplateEscapingPassthrough.expected | 276 ++++++++++-------- .../CWE-79/HTMLTemplateEscapingPassthrough.go | 46 +++ 2 files changed, 193 insertions(+), 129 deletions(-) diff --git a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected index e2e8e79ad26..ea2cdc54019 100644 --- a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected +++ b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected @@ -1,133 +1,151 @@ edges -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | -| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | -| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | -| HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | +| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | +| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | +| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | +| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | +| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | +| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | +| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | +| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | +| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | +| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | +| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | +| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | +| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | +| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | +| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | +| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | +| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | +| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | +| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | +| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | +| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | +| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | +| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | +| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | +| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | +| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | +| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | +| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | +| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:82:16:82:33 | type conversion | +| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | +| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | +| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | +| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | +| HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | +| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | +| HTMLTemplateEscapingPassthrough.go:101:9:101:14 | selection of Form | HTMLTemplateEscapingPassthrough.go:101:9:101:24 | call to Get | +| HTMLTemplateEscapingPassthrough.go:101:9:101:24 | call to Get | HTMLTemplateEscapingPassthrough.go:115:8:115:15 | call to getId | +| HTMLTemplateEscapingPassthrough.go:104:18:104:18 | definition of x | HTMLTemplateEscapingPassthrough.go:105:9:105:24 | type conversion | +| HTMLTemplateEscapingPassthrough.go:105:9:105:24 | type conversion | HTMLTemplateEscapingPassthrough.go:123:11:123:36 | call to passthrough | +| HTMLTemplateEscapingPassthrough.go:108:35:108:35 | definition of x | HTMLTemplateEscapingPassthrough.go:110:19:110:19 | x | +| HTMLTemplateEscapingPassthrough.go:115:8:115:15 | call to getId | HTMLTemplateEscapingPassthrough.go:116:15:116:15 | x | +| HTMLTemplateEscapingPassthrough.go:116:15:116:15 | x | HTMLTemplateEscapingPassthrough.go:104:18:104:18 | definition of x | +| HTMLTemplateEscapingPassthrough.go:123:11:123:36 | call to passthrough | HTMLTemplateEscapingPassthrough.go:108:35:108:35 | definition of x | nodes -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g | -| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | semmle.label | escaped | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | semmle.label | src | -| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent | semmle.label | call to UserAgent | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion | -| HTMLTemplateEscapingPassthrough.go:90:38:90:67 | call to HTMLEscapeString | semmle.label | call to HTMLEscapeString | -| HTMLTemplateEscapingPassthrough.go:90:64:90:66 | src | semmle.label | src | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | -| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted | +| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | semmle.label | a | +| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | semmle.label | c | +| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | semmle.label | c | +| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | semmle.label | d | +| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | semmle.label | d | +| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | semmle.label | e | +| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | semmle.label | e | +| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | semmle.label | b | +| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | semmle.label | b | +| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | semmle.label | f | +| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | semmle.label | f | +| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | semmle.label | g | +| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | semmle.label | g | +| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | semmle.label | escaped | +| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:82:16:82:33 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | semmle.label | src | +| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | semmle.label | call to UserAgent | +| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | semmle.label | call to HTMLEscapeString | +| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | semmle.label | src | +| HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | semmle.label | converted | +| HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | semmle.label | converted | +| HTMLTemplateEscapingPassthrough.go:101:9:101:14 | selection of Form | semmle.label | selection of Form | +| HTMLTemplateEscapingPassthrough.go:101:9:101:24 | call to Get | semmle.label | call to Get | +| HTMLTemplateEscapingPassthrough.go:104:18:104:18 | definition of x | semmle.label | definition of x | +| HTMLTemplateEscapingPassthrough.go:105:9:105:24 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:105:9:105:24 | type conversion | semmle.label | type conversion | +| HTMLTemplateEscapingPassthrough.go:108:35:108:35 | definition of x | semmle.label | definition of x | +| HTMLTemplateEscapingPassthrough.go:110:19:110:19 | x | semmle.label | x | +| HTMLTemplateEscapingPassthrough.go:115:8:115:15 | call to getId | semmle.label | call to getId | +| HTMLTemplateEscapingPassthrough.go:116:15:116:15 | x | semmle.label | x | +| HTMLTemplateEscapingPassthrough.go:123:11:123:36 | call to passthrough | semmle.label | call to passthrough | subpaths #select -| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | converted | -| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | converted | +| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | converted | diff --git a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go index f001bc93138..de353c861cf 100644 --- a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go +++ b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go @@ -4,6 +4,7 @@ import ( "html/template" "net/http" "os" + "strconv" ) func main() {} @@ -91,3 +92,48 @@ func good(req *http.Request) { checkError(tmpl.Execute(os.Stdout, converted)) } } + +// good: the following example demonstrates data flow from untrusted input +// to a passthrough type and data flow from a passthrough type to +// a template, but crucially no data flow from the untrusted input to the +// template without a sanitizer. +func getId(r *http.Request) string { + return r.Form.Get("id") // untrusted +} + +func passthrough(x string) template.HTML { + return template.HTML(x) // passthrough type +} + +func sink(wr http.ResponseWriter, x any) { + tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`) + tmpl.Execute(wr, x) // template sink +} + +func source2waypoint() { + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { + x := getId(r) + passthrough(x) // untrusted input goes to the passthrough type + }) +} + +func waypoint2sink() { + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { + // passthrough type with trusted input goes to the sink + sink(w, passthrough("not tainted")) + }) +} + +func source2sinkSanitized() { + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { + x := getId(r) // untrusted input + // TODO: We expected this test to fail with the current implementation, since the A->C + // taint tracking configuration does not actually check for sanitizers. However, the + // sink in `sink` only gets flagged if we remove the line with the sanitizer here. + // While this behaviour is desired, it's unclear why it works right now. + // Once we rewrite the query using the new data flow implementation, we should + // probably use flow states for this query, which will then also address this issue. + y, _ := strconv.Atoi(x) // sanitizer + sink(w, y) // sink + }) +} From 1b75afb5b10a74bd1bf726d42e9db28957059dc6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 28 Apr 2023 14:30:48 +0200 Subject: [PATCH 81/96] JS: Change note --- .../ql/src/change-notes/2023-04-28-json-with-comments.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 javascript/ql/src/change-notes/2023-04-28-json-with-comments.md diff --git a/javascript/ql/src/change-notes/2023-04-28-json-with-comments.md b/javascript/ql/src/change-notes/2023-04-28-json-with-comments.md new file mode 100644 index 00000000000..3ce9949a39a --- /dev/null +++ b/javascript/ql/src/change-notes/2023-04-28-json-with-comments.md @@ -0,0 +1,5 @@ +--- +category: fix +--- +* Fixed a spurious diagnostic warning about comments in JSON files being illegal. + Comments in JSON files are in fact fully supported, and the diagnostic message was misleading. From 77ec181cac587b239001a118ce52c1e5941a29c4 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 28 Apr 2023 14:49:04 +0200 Subject: [PATCH 82/96] Java: Fix sink model generator for instance parameters --- .../src/utils/modelgenerator/internal/CaptureModelsSpecific.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 349af01f790..12bfee05569 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -236,7 +236,7 @@ predicate apiSource(DataFlow::Node source) { string asInputArgumentSpecific(DataFlow::Node source) { exists(int pos | source.(DataFlow::ParameterNode).isParameterOf(_, pos) and - result = "Argument[" + pos + "]" + if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString() ) or source.asExpr() instanceof J::FieldAccess and From a7d238f4c4ac086370c54c248bbde56110a16074 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 28 Apr 2023 22:41:58 +0100 Subject: [PATCH 83/96] C++: Accept consistency changes. --- .../library-tests/syntax-zoo/dataflow-ir-consistency.expected | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index fc71b416281..6ba1cdf8ed7 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -4,7 +4,9 @@ uniqueType uniqueNodeLocation missingLocation uniqueNodeToString +| cpp11.cpp:50:15:50:16 | (no string representation) | Node should have one toString but has 0. | missingToString +| Nodes without toString: 1 | parameterCallable localFlowIsLocal readStepIsLocal From 36ea61c25ec8714669a0e7cb102b7a38b2b3e137 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 1 May 2023 10:26:51 +0200 Subject: [PATCH 84/96] C#: Address review comments. --- config/identical-files.json | 1 - .../dataflow/internal/ContentDataFlow.qll | 23 +- .../DataFlowImplForContentDataFlow.qll | 398 ------------------ .../dataflow/content/ContentFlow.ql | 2 +- 4 files changed, 10 insertions(+), 414 deletions(-) delete mode 100644 csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll diff --git a/config/identical-files.json b/config/identical-files.json index d694c69f9bc..3a9ef5173aa 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -40,7 +40,6 @@ "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll", - "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll", diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll index 4fa60e9e3ae..9d483900aeb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll @@ -24,6 +24,7 @@ */ private import csharp +private import codeql.util.Boolean private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Private as DataFlowPrivate @@ -31,7 +32,7 @@ private import DataFlowImplSpecific::Private as DataFlowPrivate /** * An input configuration for content data flow. */ -signature module ContentConfigSig { +signature module ConfigSig { /** * Holds if `source` is a relevant data flow source. */ @@ -76,7 +77,7 @@ signature module ContentConfigSig { /** * Constructs a global content data flow computation. */ -module Global implements DataFlow::GlobalFlowSig { +module Global { private module FlowConfig implements DataFlow::StateConfigSig { class FlowState = State; @@ -116,8 +117,6 @@ module Global implements DataFlow::GlobalFlowSig private module Flow = DataFlow::GlobalWithState; - import Flow - /** * Holds if data stored inside `sourceAp` on `source` flows to `sinkAp` inside `sink` * for this configuration. `preservesValue` indicates whether any of the additional @@ -131,7 +130,7 @@ module Global implements DataFlow::GlobalFlowSig * that was last stored into. That is, if `sinkAp` is `Field1.Field2` (with `Field1` * being the top of the stack), then there is flow into `sink.Field1.Field2`. */ - additional predicate flow( + predicate flow( DataFlow::Node source, AccessPath sourceAp, DataFlow::Node sink, AccessPath sinkAp, boolean preservesValue ) { @@ -150,15 +149,11 @@ module Global implements DataFlow::GlobalFlowSig } private newtype TState = - TInitState(boolean preservesValue) { preservesValue in [false, true] } or - TStoreState(int size, boolean preservesValue) { - size in [1 .. ContentConfig::accessPathLimit()] and - preservesValue in [false, true] + TInitState(Boolean preservesValue) or + TStoreState(int size, Boolean preservesValue) { + size in [1 .. ContentConfig::accessPathLimit()] } or - TReadState(int size, boolean preservesValue) { - size in [1 .. ContentConfig::accessPathLimit()] and - preservesValue in [false, true] - } + TReadState(int size, Boolean preservesValue) { size in [1 .. ContentConfig::accessPathLimit()] } abstract private class State extends TState { abstract string toString(); @@ -260,7 +255,7 @@ module Global implements DataFlow::GlobalFlowSig } /** An access path. */ - additional class AccessPath extends TAccessPath { + class AccessPath extends TAccessPath { /** Gets the head of this access path, if any. */ DataFlow::ContentSet getHead() { this = TAccessPathCons(result, _) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll deleted file mode 100644 index be70086a93a..00000000000 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ /dev/null @@ -1,398 +0,0 @@ -/** - * DEPRECATED: Use `Global` and `GlobalWithState` instead. - * - * Provides a `Configuration` class backwards-compatible interface to the data - * flow library. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -private import DataFlowImpl -import DataFlowImplCommonPublic -import FlowStateString -private import codeql.util.Unit - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - * - * These features are generally not relevant for typical end-to-end data flow - * queries, but should only be used for constructing paths that need to - * somehow be pluggable in another path context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * DEPRECATED: Use `FlowExploration` instead. - * - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - deprecated int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -private FlowState relevantState(Configuration config) { - config.isSource(_, result) or - config.isSink(_, result) or - config.isBarrier(_, result) or - config.isAdditionalFlowStep(_, result, _, _) or - config.isAdditionalFlowStep(_, _, _, result) -} - -private newtype TConfigState = - TMkConfigState(Configuration config, FlowState state) { - state = relevantState(config) or state instanceof FlowStateEmpty - } - -private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } - -private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } - -private predicate singleConfiguration() { 1 = strictcount(Configuration c) } - -private module Config implements FullStateConfigSig { - class FlowState = TConfigState; - - predicate isSource(Node source, FlowState state) { - getConfig(state).isSource(source, getState(state)) - or - getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty - } - - predicate isSink(Node sink, FlowState state) { - getConfig(state).isSink(sink, getState(state)) - or - getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty - } - - predicate isBarrier(Node node) { none() } - - predicate isBarrier(Node node, FlowState state) { - getConfig(state).isBarrier(node, getState(state)) or - getConfig(state).isBarrier(node) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) - } - - predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } - - predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } - - predicate isAdditionalFlowStep(Node node1, Node node2) { - singleConfiguration() and - any(Configuration config).isAdditionalFlowStep(node1, node2) - } - - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and - getConfig(state2) = getConfig(state1) - or - not singleConfiguration() and - getConfig(state1).isAdditionalFlowStep(node1, node2) and - state2 = state1 - } - - predicate allowImplicitRead(Node node, ContentSet c) { - any(Configuration config).allowImplicitRead(node, c) - } - - int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - - FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - - predicate sourceGrouping(Node source, string sourceGroup) { - any(Configuration config).sourceGrouping(source, sourceGroup) - } - - predicate sinkGrouping(Node sink, string sinkGroup) { - any(Configuration config).sinkGrouping(sink, sinkGroup) - } - - predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } -} - -private import Impl as I - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof I::PathNode { - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { result = super.getNode() } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = getState(super.getState()) } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = getConfig(super.getState()) } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getASuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { super.isSourceGroup(group) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { super.isSinkGroup(group) } -} - -module PathGraph = I::PathGraph; - -private predicate hasFlow(Node source, Node sink, Configuration config) { - exists(PathNode source0, PathNode sink0 | - hasFlowPath(source0, sink0, config) and - source0.getNode() = source and - sink0.getNode() = sink - ) -} - -private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - I::flowPath(source, sink) and source.getConfiguration() = config -} - -private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } - -predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql b/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql index 459f49cc8d5..e5f594ca806 100644 --- a/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql +++ b/csharp/ql/test/library-tests/dataflow/content/ContentFlow.ql @@ -1,7 +1,7 @@ import csharp import semmle.code.csharp.dataflow.internal.ContentDataFlow as ContentDataFlow -module ContentConfig implements ContentDataFlow::ContentConfigSig { +module ContentConfig implements ContentDataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } predicate isSink(DataFlow::Node sink) { From 4687ac16ff0c23431c4022808c2043a5a8755d0c Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 1 May 2023 11:48:16 +0200 Subject: [PATCH 85/96] Type tracking: Use `noopt`+`inline_late` in `TypeTracker::[small]step` --- .../codeql/typetracking/TypeTracking.qll | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/shared/typetracking/codeql/typetracking/TypeTracking.qll b/shared/typetracking/codeql/typetracking/TypeTracking.qll index d289a11a29a..6bfc31db5f3 100644 --- a/shared/typetracking/codeql/typetracking/TypeTracking.qll +++ b/shared/typetracking/codeql/typetracking/TypeTracking.qll @@ -461,6 +461,40 @@ module TypeTracking { stepSplit(nodeFrom, nodeTo, summary) } + pragma[nomagic] + private predicate stepProj(LocalSourceNode nodeFrom, StepSummary summary) { + step(nodeFrom, _, summary) + } + + bindingset[t, nodeFrom] + pragma[inline_late] + pragma[noopt] + private TypeTracker stepInlineLate(TypeTracker t, LocalSourceNode nodeFrom, LocalSourceNode nodeTo) { + exists(StepSummary summary | + stepProj(nodeFrom, summary) and + result = append(t, summary) and + step(nodeFrom, nodeTo, summary) + ) + } + + pragma[nomagic] + private predicate smallStepProj(LocalSourceNode nodeFrom, StepSummary summary) { + smallStep(nodeFrom, _, summary) + } + + bindingset[t, nodeFrom] + pragma[inline_late] + pragma[noopt] + private TypeTracker smallStepInlineLate( + TypeTracker t, LocalSourceNode nodeFrom, LocalSourceNode nodeTo + ) { + exists(StepSummary summary | + smallStepProj(nodeFrom, summary) and + result = append(t, summary) and + smallStep(nodeFrom, nodeTo, summary) + ) + } + /** * A summary of the steps needed to track a value to a given dataflow node. * @@ -493,9 +527,6 @@ module TypeTracking { TypeTracker() { this = MkTypeTracker(hasCall, content) } - /** Gets the summary resulting from appending `step` to this type-tracking summary. */ - private TypeTracker append(StepSummary step) { result = append(this, step) } - /** Gets a textual representation of this summary. */ string toString() { exists(string withCall, string withContent | @@ -553,13 +584,9 @@ module TypeTracking { * Gets the summary that corresponds to having taken a forwards * heap and/or inter-procedural step from `nodeFrom` to `nodeTo`. */ - bindingset[nodeFrom, this] + pragma[inline] TypeTracker step(LocalSourceNode nodeFrom, LocalSourceNode nodeTo) { - exists(StepSummary summary | - step(pragma[only_bind_out](nodeFrom), _, pragma[only_bind_into](summary)) and - result = pragma[only_bind_into](pragma[only_bind_out](this)).append(summary) and - step(pragma[only_bind_into](pragma[only_bind_out](nodeFrom)), nodeTo, summary) - ) + result = stepInlineLate(this, nodeFrom, nodeTo) } /** @@ -586,13 +613,9 @@ module TypeTracking { * } * ``` */ - bindingset[nodeFrom, this] + pragma[inline] TypeTracker smallstep(Node nodeFrom, Node nodeTo) { - exists(StepSummary summary | - smallStep(pragma[only_bind_out](nodeFrom), _, pragma[only_bind_into](summary)) and - result = pragma[only_bind_into](pragma[only_bind_out](this)).append(summary) and - smallStep(pragma[only_bind_into](pragma[only_bind_out](nodeFrom)), nodeTo, summary) - ) + result = smallStepInlineLate(this, nodeFrom, nodeTo) or simpleLocalSmallStep(nodeFrom, nodeTo) and result = this From 5d15ec99c861324bf2496ca12c413733f0c541fc Mon Sep 17 00:00:00 2001 From: Maiky <76447395+maikypedia@users.noreply.github.com> Date: Tue, 2 May 2023 09:26:41 +0200 Subject: [PATCH 86/96] Change expected file to new --- .../TemplateInjection.expected | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected index d7a76ef930a..f92dd2c2233 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected @@ -1,42 +1,42 @@ edges -| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:8:5:8:12 | bad_text : | -| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:11:11:11:14 | name : | -| ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:5:12:5:24 | ...[...] : | -| ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:5:5:5:8 | name : | -| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:15:24:15:31 | bad_text | -| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:19:20:19:27 | bad_text | -| ErbInjection.rb:8:16:11:14 | ... % ... : | ErbInjection.rb:8:5:8:12 | bad_text : | -| ErbInjection.rb:11:11:11:14 | name : | ErbInjection.rb:8:16:11:14 | ... % ... : | -| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:8:5:8:12 | bad_text : | -| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:11:11:11:14 | name : | -| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:17:5:17:13 | bad2_text : | -| SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:5:12:5:24 | ...[...] : | -| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:5:5:5:8 | name : | -| SlimInjection.rb:8:5:8:12 | bad_text : | SlimInjection.rb:14:25:14:32 | bad_text | -| SlimInjection.rb:8:16:11:14 | ... % ... : | SlimInjection.rb:8:5:8:12 | bad_text : | -| SlimInjection.rb:11:11:11:14 | name : | SlimInjection.rb:8:16:11:14 | ... % ... : | -| SlimInjection.rb:17:5:17:13 | bad2_text : | SlimInjection.rb:23:25:23:33 | bad2_text | +| ErbInjection.rb:5:5:5:8 | name | ErbInjection.rb:8:5:8:12 | bad_text | +| ErbInjection.rb:5:5:5:8 | name | ErbInjection.rb:11:11:11:14 | name | +| ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:5:12:5:24 | ...[...] | +| ErbInjection.rb:5:12:5:24 | ...[...] | ErbInjection.rb:5:5:5:8 | name | +| ErbInjection.rb:8:5:8:12 | bad_text | ErbInjection.rb:15:24:15:31 | bad_text | +| ErbInjection.rb:8:5:8:12 | bad_text | ErbInjection.rb:19:20:19:27 | bad_text | +| ErbInjection.rb:8:16:11:14 | ... % ... | ErbInjection.rb:8:5:8:12 | bad_text | +| ErbInjection.rb:11:11:11:14 | name | ErbInjection.rb:8:16:11:14 | ... % ... | +| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:8:5:8:12 | bad_text | +| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:11:11:11:14 | name | +| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:17:5:17:13 | bad2_text | +| SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:5:12:5:24 | ...[...] | +| SlimInjection.rb:5:12:5:24 | ...[...] | SlimInjection.rb:5:5:5:8 | name | +| SlimInjection.rb:8:5:8:12 | bad_text | SlimInjection.rb:14:25:14:32 | bad_text | +| SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:8:5:8:12 | bad_text | +| SlimInjection.rb:11:11:11:14 | name | SlimInjection.rb:8:16:11:14 | ... % ... | +| SlimInjection.rb:17:5:17:13 | bad2_text | SlimInjection.rb:23:25:23:33 | bad2_text | nodes -| ErbInjection.rb:5:5:5:8 | name : | semmle.label | name : | -| ErbInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | -| ErbInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | -| ErbInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | -| ErbInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | -| ErbInjection.rb:11:11:11:14 | name : | semmle.label | name : | +| ErbInjection.rb:5:5:5:8 | name | semmle.label | name | +| ErbInjection.rb:5:12:5:17 | call to params | semmle.label | call to params | +| ErbInjection.rb:5:12:5:24 | ...[...] | semmle.label | ...[...] | +| ErbInjection.rb:8:5:8:12 | bad_text | semmle.label | bad_text | +| ErbInjection.rb:8:16:11:14 | ... % ... | semmle.label | ... % ... | +| ErbInjection.rb:11:11:11:14 | name | semmle.label | name | | ErbInjection.rb:15:24:15:31 | bad_text | semmle.label | bad_text | | ErbInjection.rb:19:20:19:27 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:5:5:5:8 | name : | semmle.label | name : | -| SlimInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | -| SlimInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | -| SlimInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | -| SlimInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | -| SlimInjection.rb:11:11:11:14 | name : | semmle.label | name : | +| SlimInjection.rb:5:5:5:8 | name | semmle.label | name | +| SlimInjection.rb:5:12:5:17 | call to params | semmle.label | call to params | +| SlimInjection.rb:5:12:5:24 | ...[...] | semmle.label | ...[...] | +| SlimInjection.rb:8:5:8:12 | bad_text | semmle.label | bad_text | +| SlimInjection.rb:8:16:11:14 | ... % ... | semmle.label | ... % ... | +| SlimInjection.rb:11:11:11:14 | name | semmle.label | name | | SlimInjection.rb:14:25:14:32 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:17:5:17:13 | bad2_text : | semmle.label | bad2_text : | +| SlimInjection.rb:17:5:17:13 | bad2_text | semmle.label | bad2_text | | SlimInjection.rb:23:25:23:33 | bad2_text | semmle.label | bad2_text | subpaths #select -| ErbInjection.rb:15:24:15:31 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:15:24:15:31 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | -| ErbInjection.rb:19:20:19:27 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:19:20:19:27 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | -| SlimInjection.rb:14:25:14:32 | bad_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:14:25:14:32 | bad_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | -| SlimInjection.rb:23:25:23:33 | bad2_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:23:25:23:33 | bad2_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | +| ErbInjection.rb:15:24:15:31 | bad_text | ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:15:24:15:31 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | +| ErbInjection.rb:19:20:19:27 | bad_text | ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:19:20:19:27 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | +| SlimInjection.rb:14:25:14:32 | bad_text | SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:14:25:14:32 | bad_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | +| SlimInjection.rb:23:25:23:33 | bad2_text | SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:23:25:23:33 | bad2_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | From 5927bb2030d4b234f16016cfe60cbeb391f925cd Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 2 May 2023 09:48:34 +0200 Subject: [PATCH 87/96] Dataflow: Replace "extends Node" with "instanceof Node". --- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../new/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- .../dataflow/internal/DataFlowImplCommon.qll | 20 ++++++++++++++----- 8 files changed, 120 insertions(+), 40 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll index 330e59567f2..2d1b7c3a115 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll @@ -961,8 +961,10 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { /** * A `Node` at which a cast can occur such that the type should be checked. */ -class CastingNode extends Node { +class CastingNode instanceof Node { CastingNode() { castingNode(this) } + + string toString() { result = super.toString() } } private predicate readStepWithTypes( @@ -1110,9 +1112,11 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ -class ParamNode extends Node { +class ParamNode instanceof Node { ParamNode() { parameterNode(this, _, _) } + string toString() { result = super.toString() } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1121,9 +1125,11 @@ class ParamNode extends Node { } /** A data-flow node that represents a call argument. */ -class ArgNode extends Node { +class ArgNode instanceof Node { ArgNode() { argumentNode(this, _, _) } + string toString() { result = super.toString() } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1134,9 +1140,11 @@ class ArgNode extends Node { * A node from which flow can return to the caller. This is either a regular * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. */ -class ReturnNodeExt extends Node { +class ReturnNodeExt instanceof Node { ReturnNodeExt() { returnNodeExt(this, _) } + string toString() { result = super.toString() } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1145,8 +1153,10 @@ class ReturnNodeExt extends Node { * A node to which data can flow from a call. Either an ordinary out node * or a post-update node associated with a call argument. */ -class OutNodeExt extends Node { +class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } + + string toString() { result = super.toString() } } /** From fbc872cf1d4a5892ff404b0824c0a3b624a8507b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 2 May 2023 09:07:57 +0100 Subject: [PATCH 88/96] Update cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com> --- cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md b/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md index 3c7069f7050..be4c4e73ed0 100644 --- a/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md +++ b/cpp/ql/lib/change-notes/2023-04-28-static-local-dataflow.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now supports tracking flow through static local variables. +* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables. From 2001ce34d4d9dfbe5acb031d32e5d4e7d1ea4a4d Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 2 May 2023 10:18:37 +0200 Subject: [PATCH 89/96] Java/C#: Adjust references. --- csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll | 2 +- .../src/utils/modelgenerator/internal/CaptureModelsSpecific.qll | 2 +- java/ql/src/utils/modelgenerator/internal/CaptureModels.qll | 2 +- .../src/utils/modelgenerator/internal/CaptureModelsSpecific.qll | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 11bd2f32b58..e2a0e130ca4 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -178,7 +178,7 @@ string captureThroughFlow(DataFlowTargetApi api) { string output | ThroughFlow::flow(p, returnNodeExt) and - returnNodeExt.getEnclosingCallable() = api and + returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and input = parameterNodeAsInput(p) and output = returnNodeAsOutput(returnNodeExt) and input != output and diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index ea45e8e049b..29ab8a2c1dc 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -121,7 +121,7 @@ class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode; pragma[nomagic] private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, ParameterPosition pos) { - result = node.getEnclosingCallable().getParameter(pos.getPosition()) + result = node.(DataFlow::Node).getEnclosingCallable().getParameter(pos.getPosition()) } /** diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 11bd2f32b58..e2a0e130ca4 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -178,7 +178,7 @@ string captureThroughFlow(DataFlowTargetApi api) { string output | ThroughFlow::flow(p, returnNodeExt) and - returnNodeExt.getEnclosingCallable() = api and + returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and input = parameterNodeAsInput(p) and output = returnNodeAsOutput(returnNodeExt) and input != output and diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 349af01f790..e14850a5538 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -184,7 +184,7 @@ string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) { exists(int pos | pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() | - result = parameterAccess(node.getEnclosingCallable().getParameter(pos)) + result = parameterAccess(node.(DataFlow::Node).getEnclosingCallable().getParameter(pos)) or result = qualifierString() and pos = -1 ) From f59c149bae1e972c19771021725c304abee72665 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 2 May 2023 10:46:55 +0200 Subject: [PATCH 90/96] Ruby: add SQL injection sinks to meta query --- ruby/ql/src/queries/meta/internal/TaintMetrics.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ruby/ql/src/queries/meta/internal/TaintMetrics.qll b/ruby/ql/src/queries/meta/internal/TaintMetrics.qll index 7768828caf6..b3a716c6686 100644 --- a/ruby/ql/src/queries/meta/internal/TaintMetrics.qll +++ b/ruby/ql/src/queries/meta/internal/TaintMetrics.qll @@ -8,6 +8,7 @@ private import codeql.ruby.security.PathInjectionCustomizations private import codeql.ruby.security.ServerSideRequestForgeryCustomizations private import codeql.ruby.security.UnsafeDeserializationCustomizations private import codeql.ruby.security.UrlRedirectCustomizations +private import codeql.ruby.security.SqlInjectionCustomizations class RelevantFile extends File { RelevantFile() { not getRelativePath().regexpMatch(".*/test(case)?s?/.*") } @@ -34,6 +35,8 @@ DataFlow::Node relevantTaintSink(string kind) { kind = "UnsafeDeserialization" and result instanceof UnsafeDeserialization::Sink or kind = "UrlRedirect" and result instanceof UrlRedirect::Sink + or + kind = "SqlInjection" and result instanceof SqlInjection::Sink ) and // the sink is not a string literal not exists(Ast::StringLiteral str | From ca0964967945156c20e4579d2fc83ac754a57d9b Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 2 May 2023 10:48:32 +0200 Subject: [PATCH 91/96] Dataflow: Forward hasLocationInfo. --- .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../new/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ .../dataflow/internal/DataFlowImplCommon.qll | 30 +++++++++++++++++++ 8 files changed, 240 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll index 2d1b7c3a115..0d4c033c95d 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll @@ -965,6 +965,12 @@ class CastingNode instanceof Node { CastingNode() { castingNode(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private predicate readStepWithTypes( @@ -1117,6 +1123,12 @@ class ParamNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Holds if this node is the parameter of callable `c` at the specified * position. @@ -1130,6 +1142,12 @@ class ArgNode instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Holds if this argument occurs at the given position in the given call. */ final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { argumentNode(this, call, pos) @@ -1145,6 +1163,12 @@ class ReturnNodeExt instanceof Node { string toString() { result = super.toString() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** Gets the kind of this returned value. */ ReturnKindExt getKind() { returnNodeExt(this, result) } } @@ -1157,6 +1181,12 @@ class OutNodeExt instanceof Node { OutNodeExt() { outNodeExt(this) } string toString() { result = super.toString() } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } /** From 635d290504903259e712e3b5ed61bf4f674c4418 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 2 May 2023 13:51:16 +0100 Subject: [PATCH 92/96] C++: Add testcase with FP. --- .../CWE/CWE-119/OverrunWriteProductFlow.expected | 8 ++++++++ .../query-tests/Security/CWE/CWE-119/test.cpp | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 93351da51f1..69174ec8f91 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -209,6 +209,9 @@ edges | test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string | | test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string indirection | | test.cpp:207:22:207:27 | string indirection | test.cpp:207:22:207:27 | string | +| test.cpp:214:24:214:24 | p | test.cpp:216:10:216:10 | p | +| test.cpp:220:43:220:48 | call to malloc | test.cpp:222:15:222:20 | buffer | +| test.cpp:222:15:222:20 | buffer | test.cpp:214:24:214:24 | p | nodes | test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] | | test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... | @@ -374,6 +377,10 @@ nodes | test.cpp:207:17:207:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:207:22:207:27 | string | semmle.label | string | | test.cpp:207:22:207:27 | string indirection | semmle.label | string indirection | +| test.cpp:214:24:214:24 | p | semmle.label | p | +| test.cpp:216:10:216:10 | p | semmle.label | p | +| test.cpp:220:43:220:48 | call to malloc | semmle.label | call to malloc | +| test.cpp:222:15:222:20 | buffer | semmle.label | buffer | subpaths #select | test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | string | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string | @@ -391,3 +398,4 @@ subpaths | test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string | | test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | | test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | +| test.cpp:216:3:216:8 | call to memset | test.cpp:220:43:220:48 | call to malloc | test.cpp:216:10:216:10 | p | This write may overflow $@ by 5 elements. | test.cpp:216:10:216:10 | p | p | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp index c42e08feb9c..8ce2be9cd10 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp @@ -208,3 +208,16 @@ void test5(unsigned size, char *buf, unsigned anotherSize) { } } + +void *memset(void *, int, unsigned); + +void call_memset(void *p, unsigned size) +{ + memset(p, 0, size); // GOOD [FALSE POSITIVE] +} + +void test_missing_call_context(unsigned char *unrelated_buffer, unsigned size) { + unsigned char* buffer = (unsigned char*)malloc(size); + call_memset(unrelated_buffer, size + 5); + call_memset(buffer, size); +} \ No newline at end of file From a571bc64ac49857c6222fbcb7186db804c947317 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 2 May 2023 16:14:20 +0100 Subject: [PATCH 93/96] ruby: regenerate TemplateInjection.expected --- .../TemplateInjection.expected | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected index f92dd2c2233..d7a76ef930a 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected @@ -1,42 +1,42 @@ edges -| ErbInjection.rb:5:5:5:8 | name | ErbInjection.rb:8:5:8:12 | bad_text | -| ErbInjection.rb:5:5:5:8 | name | ErbInjection.rb:11:11:11:14 | name | -| ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:5:12:5:24 | ...[...] | -| ErbInjection.rb:5:12:5:24 | ...[...] | ErbInjection.rb:5:5:5:8 | name | -| ErbInjection.rb:8:5:8:12 | bad_text | ErbInjection.rb:15:24:15:31 | bad_text | -| ErbInjection.rb:8:5:8:12 | bad_text | ErbInjection.rb:19:20:19:27 | bad_text | -| ErbInjection.rb:8:16:11:14 | ... % ... | ErbInjection.rb:8:5:8:12 | bad_text | -| ErbInjection.rb:11:11:11:14 | name | ErbInjection.rb:8:16:11:14 | ... % ... | -| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:8:5:8:12 | bad_text | -| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:11:11:11:14 | name | -| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:17:5:17:13 | bad2_text | -| SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:5:12:5:24 | ...[...] | -| SlimInjection.rb:5:12:5:24 | ...[...] | SlimInjection.rb:5:5:5:8 | name | -| SlimInjection.rb:8:5:8:12 | bad_text | SlimInjection.rb:14:25:14:32 | bad_text | -| SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:8:5:8:12 | bad_text | -| SlimInjection.rb:11:11:11:14 | name | SlimInjection.rb:8:16:11:14 | ... % ... | -| SlimInjection.rb:17:5:17:13 | bad2_text | SlimInjection.rb:23:25:23:33 | bad2_text | +| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:8:5:8:12 | bad_text : | +| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:11:11:11:14 | name : | +| ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:5:12:5:24 | ...[...] : | +| ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:5:5:5:8 | name : | +| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:15:24:15:31 | bad_text | +| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:19:20:19:27 | bad_text | +| ErbInjection.rb:8:16:11:14 | ... % ... : | ErbInjection.rb:8:5:8:12 | bad_text : | +| ErbInjection.rb:11:11:11:14 | name : | ErbInjection.rb:8:16:11:14 | ... % ... : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:8:5:8:12 | bad_text : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:11:11:11:14 | name : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:17:5:17:13 | bad2_text : | +| SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:5:12:5:24 | ...[...] : | +| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:5:5:5:8 | name : | +| SlimInjection.rb:8:5:8:12 | bad_text : | SlimInjection.rb:14:25:14:32 | bad_text | +| SlimInjection.rb:8:16:11:14 | ... % ... : | SlimInjection.rb:8:5:8:12 | bad_text : | +| SlimInjection.rb:11:11:11:14 | name : | SlimInjection.rb:8:16:11:14 | ... % ... : | +| SlimInjection.rb:17:5:17:13 | bad2_text : | SlimInjection.rb:23:25:23:33 | bad2_text | nodes -| ErbInjection.rb:5:5:5:8 | name | semmle.label | name | -| ErbInjection.rb:5:12:5:17 | call to params | semmle.label | call to params | -| ErbInjection.rb:5:12:5:24 | ...[...] | semmle.label | ...[...] | -| ErbInjection.rb:8:5:8:12 | bad_text | semmle.label | bad_text | -| ErbInjection.rb:8:16:11:14 | ... % ... | semmle.label | ... % ... | -| ErbInjection.rb:11:11:11:14 | name | semmle.label | name | +| ErbInjection.rb:5:5:5:8 | name : | semmle.label | name : | +| ErbInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | +| ErbInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | +| ErbInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | +| ErbInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | +| ErbInjection.rb:11:11:11:14 | name : | semmle.label | name : | | ErbInjection.rb:15:24:15:31 | bad_text | semmle.label | bad_text | | ErbInjection.rb:19:20:19:27 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:5:5:5:8 | name | semmle.label | name | -| SlimInjection.rb:5:12:5:17 | call to params | semmle.label | call to params | -| SlimInjection.rb:5:12:5:24 | ...[...] | semmle.label | ...[...] | -| SlimInjection.rb:8:5:8:12 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:8:16:11:14 | ... % ... | semmle.label | ... % ... | -| SlimInjection.rb:11:11:11:14 | name | semmle.label | name | +| SlimInjection.rb:5:5:5:8 | name : | semmle.label | name : | +| SlimInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | +| SlimInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | +| SlimInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | +| SlimInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | +| SlimInjection.rb:11:11:11:14 | name : | semmle.label | name : | | SlimInjection.rb:14:25:14:32 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:17:5:17:13 | bad2_text | semmle.label | bad2_text | +| SlimInjection.rb:17:5:17:13 | bad2_text : | semmle.label | bad2_text : | | SlimInjection.rb:23:25:23:33 | bad2_text | semmle.label | bad2_text | subpaths #select -| ErbInjection.rb:15:24:15:31 | bad_text | ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:15:24:15:31 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | -| ErbInjection.rb:19:20:19:27 | bad_text | ErbInjection.rb:5:12:5:17 | call to params | ErbInjection.rb:19:20:19:27 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | -| SlimInjection.rb:14:25:14:32 | bad_text | SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:14:25:14:32 | bad_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | -| SlimInjection.rb:23:25:23:33 | bad2_text | SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:23:25:23:33 | bad2_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | +| ErbInjection.rb:15:24:15:31 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:15:24:15:31 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | +| ErbInjection.rb:19:20:19:27 | bad_text | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:19:20:19:27 | bad_text | This template depends on a $@. | ErbInjection.rb:5:12:5:17 | call to params | user-provided value | +| SlimInjection.rb:14:25:14:32 | bad_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:14:25:14:32 | bad_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | +| SlimInjection.rb:23:25:23:33 | bad2_text | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:23:25:23:33 | bad2_text | This template depends on a $@. | SlimInjection.rb:5:12:5:17 | call to params | user-provided value | From c9fba18c48a4d3e7501716a4e32810a7c34deace Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Wed, 3 May 2023 10:31:01 +0200 Subject: [PATCH 94/96] C++: Make implicit this receivers explicit --- .../raw/internal/TranslatedElement.qll | 26 +- .../raw/internal/TranslatedInitialization.qll | 297 +++++++++--------- .../raw/internal/TranslatedStmt.qll | 276 ++++++++-------- 3 files changed, 309 insertions(+), 290 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 0731656a93c..2149f148fef 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -821,7 +821,7 @@ abstract class TranslatedElement extends TTranslatedElement { abstract Locatable getAst(); /** DEPRECATED: Alias for getAst */ - deprecated Locatable getAST() { result = getAst() } + deprecated Locatable getAST() { result = this.getAst() } /** * Get the first instruction to be executed in the evaluation of this element. @@ -831,7 +831,7 @@ abstract class TranslatedElement extends TTranslatedElement { /** * Get the immediate child elements of this element. */ - final TranslatedElement getAChild() { result = getChild(_) } + final TranslatedElement getAChild() { result = this.getChild(_) } /** * Gets the immediate child element of this element. The `id` is unique @@ -844,25 +844,29 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the an identifier string for the element. This id is unique within * the scope of the element's function. */ - final int getId() { result = getUniqueId() } + final int getId() { result = this.getUniqueId() } private TranslatedElement getChildByRank(int rankIndex) { result = - rank[rankIndex + 1](TranslatedElement child, int id | child = getChild(id) | child order by id) + rank[rankIndex + 1](TranslatedElement child, int id | + child = this.getChild(id) + | + child order by id + ) } language[monotonicAggregates] private int getDescendantCount() { result = - 1 + sum(TranslatedElement child | child = getChildByRank(_) | child.getDescendantCount()) + 1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount()) } private int getUniqueId() { - if not exists(getParent()) + if not exists(this.getParent()) then result = 0 else exists(TranslatedElement parent | - parent = getParent() and + parent = this.getParent() and if this = parent.getChildByRank(0) then result = 1 + parent.getUniqueId() else @@ -908,7 +912,7 @@ abstract class TranslatedElement extends TTranslatedElement { * there is no enclosing `try`. */ Instruction getExceptionSuccessorInstruction() { - result = getParent().getExceptionSuccessorInstruction() + result = this.getParent().getExceptionSuccessorInstruction() } /** @@ -1022,14 +1026,14 @@ abstract class TranslatedElement extends TTranslatedElement { exists(Locatable ast | result.getAst() = ast and result.getTag() = tag and - hasTempVariableAndAst(tag, ast) + this.hasTempVariableAndAst(tag, ast) ) } pragma[noinline] private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) { - hasTempVariable(tag, _) and - ast = getAst() + this.hasTempVariable(tag, _) and + ast = this.getAst() } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 716d4d35c20..5392982b3b3 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -35,64 +35,64 @@ abstract class InitializationContext extends TranslatedElement { * declarations, `return` statements, and `throw` expressions. */ abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext { - final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } + final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() } final override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = InitializerVariableAddressTag() and opcode instanceof Opcode::VariableAddress and - resultType = getTypeForGLValue(getTargetType()) + resultType = getTypeForGLValue(this.getTargetType()) or - hasUninitializedInstruction() and + this.hasUninitializedInstruction() and tag = InitializerStoreTag() and opcode instanceof Opcode::Uninitialized and - resultType = getTypeForPRValue(getTargetType()) + resultType = getTypeForPRValue(this.getTargetType()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { ( tag = InitializerVariableAddressTag() and kind instanceof GotoEdge and - if hasUninitializedInstruction() - then result = getInstruction(InitializerStoreTag()) - else result = getInitialization().getFirstInstruction() + if this.hasUninitializedInstruction() + then result = this.getInstruction(InitializerStoreTag()) + else result = this.getInitialization().getFirstInstruction() ) or - hasUninitializedInstruction() and + this.hasUninitializedInstruction() and kind instanceof GotoEdge and tag = InitializerStoreTag() and ( - result = getInitialization().getFirstInstruction() + result = this.getInitialization().getFirstInstruction() or - not exists(getInitialization()) and result = getInitializationSuccessor() + not exists(this.getInitialization()) and result = this.getInitializationSuccessor() ) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getInitializationSuccessor() + child = this.getInitialization() and result = this.getInitializationSuccessor() } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - hasUninitializedInstruction() and + this.hasUninitializedInstruction() and tag = InitializerStoreTag() and operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) } final override IRVariable getInstructionVariable(InstructionTag tag) { ( tag = InitializerVariableAddressTag() or - hasUninitializedInstruction() and tag = InitializerStoreTag() + this.hasUninitializedInstruction() and tag = InitializerStoreTag() ) and - result = getIRVariable() + result = this.getIRVariable() } final override Instruction getTargetAddress() { - result = getInstruction(InitializerVariableAddressTag()) + result = this.getInstruction(InitializerVariableAddressTag()) } /** @@ -116,13 +116,13 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi */ final predicate hasUninitializedInstruction() { ( - not exists(getInitialization()) or - getInitialization() instanceof TranslatedListInitialization or - getInitialization() instanceof TranslatedConstructorInitialization or - getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _) + not exists(this.getInitialization()) or + this.getInitialization() instanceof TranslatedListInitialization or + this.getInitialization() instanceof TranslatedConstructorInitialization or + this.getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _) ) and // Variables with static or thread-local storage duration are zero-initialized at program startup. - getIRVariable() instanceof IRAutomaticVariable + this.getIRVariable() instanceof IRAutomaticVariable } } @@ -146,7 +146,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn final override Locatable getAst() { result = expr } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } /** * Gets the expression that is doing the initialization. @@ -157,7 +157,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn * Gets the initialization context that describes the location being * initialized. */ - final InitializationContext getContext() { result = getParent() } + final InitializationContext getContext() { result = this.getParent() } final TranslatedFunction getEnclosingFunction() { result = getTranslatedFunction(this.getFunction()) @@ -169,17 +169,17 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn */ abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext { override Instruction getFirstInstruction() { - result = getChild(0).getFirstInstruction() + result = this.getChild(0).getFirstInstruction() or - not exists(getChild(0)) and result = getParent().getChildSuccessor(this) + not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | - child = getChild(index) and - if exists(getChild(index + 1)) - then result = getChild(index + 1).getFirstInstruction() - else result = getParent().getChildSuccessor(this) + child = this.getChild(index) and + if exists(this.getChild(index + 1)) + then result = this.getChild(index + 1).getFirstInstruction() + else result = this.getParent().getChildSuccessor(this) ) } @@ -189,9 +189,9 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override Instruction getTargetAddress() { result = getContext().getTargetAddress() } + override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() } - override Type getTargetType() { result = getContext().getTargetType() } + override Type getTargetType() { result = this.getContext().getTargetType() } } /** @@ -237,9 +237,11 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization { abstract class TranslatedDirectInitialization extends TranslatedInitialization { TranslatedDirectInitialization() { not expr instanceof AggregateLiteral } - override TranslatedElement getChild(int id) { id = 0 and result = getInitializer() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() } - override Instruction getFirstInstruction() { result = getInitializer().getFirstInstruction() } + override Instruction getFirstInstruction() { + result = this.getInitializer().getFirstInstruction() + } final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) } } @@ -258,27 +260,27 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = InitializerStoreTag() and opcode instanceof Opcode::Store and - resultType = getTypeForPRValue(getContext().getTargetType()) + resultType = getTypeForPRValue(this.getContext().getTargetType()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getInstruction(InitializerStoreTag()) + child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getContext().getTargetAddress() + result = this.getContext().getTargetAddress() or operandTag instanceof StoreValueOperandTag and - result = getInitializer().getResult() + result = this.getInitializer().getResult() ) } } @@ -305,13 +307,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati // If the initializer string isn't large enough to fill the target, then // we have to generate another instruction sequence to store a constant // zero into the remainder of the array. - zeroInitRange(_, elementCount) and + this.zeroInitRange(_, elementCount) and ( // Create a constant zero whose size is the size of the remaining // space in the target array. tag = ZeroPadStringConstantTag() and opcode instanceof Opcode::Constant and - resultType = getUnknownOpaqueType(elementCount * getElementType().getSize()) + resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize()) or // The index of the first element to be zero initialized. tag = ZeroPadStringElementIndexTag() and @@ -321,12 +323,12 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati // Compute the address of the first element to be zero initialized. tag = ZeroPadStringElementAddressTag() and opcode instanceof Opcode::PointerAdd and - resultType = getTypeForGLValue(getElementType()) + resultType = getTypeForGLValue(this.getElementType()) or // Store the constant zero into the remainder of the string. tag = ZeroPadStringStoreTag() and opcode instanceof Opcode::Store and - resultType = getUnknownOpaqueType(elementCount * getElementType().getSize()) + resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize()) ) ) } @@ -335,78 +337,78 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati kind instanceof GotoEdge and ( tag = InitializerLoadStringTag() and - result = getInstruction(InitializerStoreTag()) + result = this.getInstruction(InitializerStoreTag()) or - if zeroInitRange(_, _) + if this.zeroInitRange(_, _) then ( tag = InitializerStoreTag() and - result = getInstruction(ZeroPadStringConstantTag()) + result = this.getInstruction(ZeroPadStringConstantTag()) or tag = ZeroPadStringConstantTag() and - result = getInstruction(ZeroPadStringElementIndexTag()) + result = this.getInstruction(ZeroPadStringElementIndexTag()) or tag = ZeroPadStringElementIndexTag() and - result = getInstruction(ZeroPadStringElementAddressTag()) + result = this.getInstruction(ZeroPadStringElementAddressTag()) or tag = ZeroPadStringElementAddressTag() and - result = getInstruction(ZeroPadStringStoreTag()) + result = this.getInstruction(ZeroPadStringStoreTag()) or tag = ZeroPadStringStoreTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) else ( tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) ) ) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getInstruction(InitializerLoadStringTag()) + child = this.getInitializer() and result = this.getInstruction(InitializerLoadStringTag()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerLoadStringTag() and ( operandTag instanceof AddressOperandTag and - result = getInitializer().getResult() + result = this.getInitializer().getResult() ) or tag = InitializerStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getContext().getTargetAddress() + result = this.getContext().getTargetAddress() or operandTag instanceof StoreValueOperandTag and - result = getInstruction(InitializerLoadStringTag()) + result = this.getInstruction(InitializerLoadStringTag()) ) or tag = ZeroPadStringElementAddressTag() and ( operandTag instanceof LeftOperandTag and - result = getContext().getTargetAddress() + result = this.getContext().getTargetAddress() or operandTag instanceof RightOperandTag and - result = getInstruction(ZeroPadStringElementIndexTag()) + result = this.getInstruction(ZeroPadStringElementIndexTag()) ) or tag = ZeroPadStringStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(ZeroPadStringElementAddressTag()) + result = this.getInstruction(ZeroPadStringElementAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getInstruction(ZeroPadStringConstantTag()) + result = this.getInstruction(ZeroPadStringConstantTag()) ) } override int getInstructionElementSize(InstructionTag tag) { tag = ZeroPadStringElementAddressTag() and - result = max(getElementType().getSize()) + result = max(this.getElementType().getSize()) } override string getInstructionConstantValue(InstructionTag tag) { exists(int startIndex | - zeroInitRange(startIndex, _) and + this.zeroInitRange(startIndex, _) and ( tag = ZeroPadStringConstantTag() and result = "0" @@ -419,13 +421,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati override predicate needsUnknownOpaqueType(int byteSize) { exists(int elementCount | - zeroInitRange(_, elementCount) and - byteSize = elementCount * getElementType().getSize() + this.zeroInitRange(_, elementCount) and + byteSize = elementCount * this.getElementType().getSize() ) } private Type getElementType() { - result = getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType() + result = this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType() } /** @@ -435,7 +437,8 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati predicate zeroInitRange(int startIndex, int elementCount) { exists(int targetCount | startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and - targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and + targetCount = + this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and elementCount = targetCount - startIndex and elementCount > 0 ) @@ -454,14 +457,14 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getParent().getChildSuccessor(this) + child = this.getInitializer() and result = this.getParent().getChildSuccessor(this) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { none() } - override Instruction getReceiver() { result = getContext().getTargetAddress() } + override Instruction getReceiver() { result = this.getContext().getTargetAddress() } } /** @@ -491,7 +494,7 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { final override Locatable getAst() { result = ast } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } final override Declaration getFunction() { result = getEnclosingFunction(ast) or @@ -499,7 +502,9 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable) } - final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(this.getFieldAddressTag()) + } /** * Gets the zero-based index describing the order in which this field is to be @@ -508,19 +513,19 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { final int getOrder() { result = field.getInitializationOrder() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { - tag = getFieldAddressTag() and + tag = this.getFieldAddressTag() and opcode instanceof Opcode::FieldAddress and resultType = getTypeForGLValue(field.getType()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - tag = getFieldAddressTag() and + tag = this.getFieldAddressTag() and operandTag instanceof UnaryOperandTag and - result = getParent().(InitializationContext).getTargetAddress() + result = this.getParent().(InitializationContext).getTargetAddress() } override Field getInstructionField(InstructionTag tag) { - tag = getFieldAddressTag() and result = field + tag = this.getFieldAddressTag() and result = field } final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() } @@ -545,21 +550,23 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio this = TTranslatedExplicitFieldInitialization(ast, field, expr, position) } - override Instruction getTargetAddress() { result = getInstruction(getFieldAddressTag()) } + override Instruction getTargetAddress() { + result = this.getInstruction(this.getFieldAddressTag()) + } override Type getTargetType() { result = field.getUnspecifiedType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - tag = getFieldAddressTag() and - result = getInitialization().getFirstInstruction() and + tag = this.getFieldAddressTag() and + result = this.getInitialization().getFirstInstruction() and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getParent().getChildSuccessor(this) + child = this.getInitialization() and result = this.getParent().getChildSuccessor(this) } - override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() } private TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr) @@ -584,11 +591,11 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType) or - tag = getFieldDefaultValueTag() and + tag = this.getFieldDefaultValueTag() and opcode instanceof Opcode::Constant and resultType = getTypeForPRValue(field.getType()) or - tag = getFieldDefaultValueStoreTag() and + tag = this.getFieldDefaultValueStoreTag() and opcode instanceof Opcode::Store and resultType = getTypeForPRValue(field.getUnspecifiedType()) } @@ -596,32 +603,32 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - tag = getFieldAddressTag() and - result = getInstruction(getFieldDefaultValueTag()) + tag = this.getFieldAddressTag() and + result = this.getInstruction(this.getFieldDefaultValueTag()) or - tag = getFieldDefaultValueTag() and - result = getInstruction(getFieldDefaultValueStoreTag()) + tag = this.getFieldDefaultValueTag() and + result = this.getInstruction(this.getFieldDefaultValueStoreTag()) or - tag = getFieldDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) + tag = this.getFieldDefaultValueStoreTag() and + result = this.getParent().getChildSuccessor(this) ) } override string getInstructionConstantValue(InstructionTag tag) { - tag = getFieldDefaultValueTag() and + tag = this.getFieldDefaultValueTag() and result = getZeroValue(field.getUnspecifiedType()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag) or - tag = getFieldDefaultValueStoreTag() and + tag = this.getFieldDefaultValueStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(getFieldAddressTag()) + result = this.getInstruction(this.getFieldAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getInstruction(getFieldDefaultValueTag()) + result = this.getInstruction(this.getFieldDefaultValueTag()) ) } @@ -644,13 +651,13 @@ abstract class TranslatedElementInitialization extends TranslatedElement { ArrayOrVectorAggregateLiteral initList; final override string toString() { - result = initList.toString() + "[" + getElementIndex().toString() + "]" + result = initList.toString() + "[" + this.getElementIndex().toString() + "]" } final override Locatable getAst() { result = initList } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } final override Declaration getFunction() { result = getEnclosingFunction(initList) @@ -660,43 +667,45 @@ abstract class TranslatedElementInitialization extends TranslatedElement { result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable) } - final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(this.getElementIndexTag()) + } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { - tag = getElementIndexTag() and + tag = this.getElementIndexTag() and opcode instanceof Opcode::Constant and resultType = getIntType() or - tag = getElementAddressTag() and + tag = this.getElementAddressTag() and opcode instanceof Opcode::PointerAdd and - resultType = getTypeForGLValue(getElementType()) + resultType = getTypeForGLValue(this.getElementType()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - tag = getElementIndexTag() and - result = getInstruction(getElementAddressTag()) and + tag = this.getElementIndexTag() and + result = this.getInstruction(this.getElementAddressTag()) and kind instanceof GotoEdge } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - tag = getElementAddressTag() and + tag = this.getElementAddressTag() and ( operandTag instanceof LeftOperandTag and - result = getParent().(InitializationContext).getTargetAddress() + result = this.getParent().(InitializationContext).getTargetAddress() or operandTag instanceof RightOperandTag and - result = getInstruction(getElementIndexTag()) + result = this.getInstruction(this.getElementIndexTag()) ) } override int getInstructionElementSize(InstructionTag tag) { - tag = getElementAddressTag() and - result = max(getElementType().getSize()) + tag = this.getElementAddressTag() and + result = max(this.getElementType().getSize()) } override string getInstructionConstantValue(InstructionTag tag) { - tag = getElementIndexTag() and - result = getElementIndex().toString() + tag = this.getElementIndexTag() and + result = this.getElementIndex().toString() } abstract int getElementIndex(); @@ -726,23 +735,25 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ this = TTranslatedExplicitElementInitialization(initList, elementIndex, position) } - override Instruction getTargetAddress() { result = getInstruction(getElementAddressTag()) } + override Instruction getTargetAddress() { + result = this.getInstruction(this.getElementAddressTag()) + } - override Type getTargetType() { result = getElementType() } + override Type getTargetType() { result = this.getElementType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or - tag = getElementAddressTag() and - result = getInitialization().getFirstInstruction() and + tag = this.getElementAddressTag() and + result = this.getInitialization().getFirstInstruction() and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getParent().getChildSuccessor(this) + child = this.getInitialization() and result = this.getParent().getChildSuccessor(this) } - override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() } override int getElementIndex() { result = elementIndex } @@ -773,13 +784,13 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType) or - tag = getElementDefaultValueTag() and + tag = this.getElementDefaultValueTag() and opcode instanceof Opcode::Constant and - resultType = getDefaultValueType() + resultType = this.getDefaultValueType() or - tag = getElementDefaultValueStoreTag() and + tag = this.getElementDefaultValueStoreTag() and opcode instanceof Opcode::Store and - resultType = getDefaultValueType() + resultType = this.getDefaultValueType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { @@ -787,34 +798,34 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati or kind instanceof GotoEdge and ( - tag = getElementAddressTag() and - result = getInstruction(getElementDefaultValueTag()) + tag = this.getElementAddressTag() and + result = this.getInstruction(this.getElementDefaultValueTag()) or - tag = getElementDefaultValueTag() and - result = getInstruction(getElementDefaultValueStoreTag()) + tag = this.getElementDefaultValueTag() and + result = this.getInstruction(this.getElementDefaultValueStoreTag()) or - tag = getElementDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) + tag = this.getElementDefaultValueStoreTag() and + result = this.getParent().getChildSuccessor(this) ) } override string getInstructionConstantValue(InstructionTag tag) { result = TranslatedElementInitialization.super.getInstructionConstantValue(tag) or - tag = getElementDefaultValueTag() and - result = getZeroValue(getElementType()) + tag = this.getElementDefaultValueTag() and + result = getZeroValue(this.getElementType()) } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { result = TranslatedElementInitialization.super.getInstructionRegisterOperand(tag, operandTag) or - tag = getElementDefaultValueStoreTag() and + tag = this.getElementDefaultValueStoreTag() and ( operandTag instanceof AddressOperandTag and - result = getInstruction(getElementAddressTag()) + result = this.getInstruction(this.getElementAddressTag()) or operandTag instanceof StoreValueOperandTag and - result = getInstruction(getElementDefaultValueTag()) + result = this.getInstruction(this.getElementDefaultValueTag()) ) } @@ -825,7 +836,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati override int getElementIndex() { result = elementIndex } override predicate needsUnknownOpaqueType(int byteSize) { - elementCount != 0 and byteSize = elementCount * getElementType().getSize() + elementCount != 0 and byteSize = elementCount * this.getElementType().getSize() } private InstructionTag getElementDefaultValueTag() { @@ -838,8 +849,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati private CppType getDefaultValueType() { if elementCount = 1 - then result = getTypeForPRValue(getElementType()) - else result = getUnknownOpaqueType(elementCount * getElementType().getSize()) + then result = getTypeForPRValue(this.getElementType()) + else result = getUnknownOpaqueType(elementCount * this.getElementType().getSize()) } } @@ -849,18 +860,18 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str final override Locatable getAst() { result = call } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } final override TranslatedElement getChild(int id) { id = 0 and - result = getStructorCall() + result = this.getStructorCall() } final override Function getFunction() { result = getEnclosingFunction(call) } final override Instruction getChildSuccessor(TranslatedElement child) { - child = getStructorCall() and - result = getParent().getChildSuccessor(this) + child = this.getStructorCall() and + result = this.getParent().getChildSuccessor(this) } final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) } @@ -871,7 +882,9 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str * destructor from within a derived class constructor or destructor. */ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor { - final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getFirstInstruction() { + result = this.getInstruction(OnlyInstructionTag()) + } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -882,15 +895,15 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and - result = getStructorCall().getFirstInstruction() + result = this.getStructorCall().getFirstInstruction() } - final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) } + final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and - result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction() } final override predicate getInstructionInheritance( @@ -898,7 +911,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru ) { tag = OnlyInstructionTag() and baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and - derivedClass = getFunction().getDeclaringType().getUnspecifiedType() + derivedClass = this.getFunction().getDeclaringType().getUnspecifiedType() } } @@ -924,7 +937,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC final override string toString() { result = "delegation construct: " + call.toString() } final override Instruction getFirstInstruction() { - result = getStructorCall().getFirstInstruction() + result = this.getStructorCall().getFirstInstruction() } final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -934,7 +947,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } final override Instruction getReceiver() { - result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction() } } @@ -981,11 +994,11 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr override Locatable getAst() { result = init } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } final override string toString() { result = "construct base (no constructor)" } - override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) } + override Instruction getFirstInstruction() { result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { none() diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index f0d8e5d3d35..497c16d407d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -240,7 +240,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { final override Locatable getAst() { result = stmt } /** DEPRECATED: Alias for getAst */ - deprecated override Locatable getAST() { result = getAst() } + deprecated override Locatable getAST() { result = this.getAst() } final override Function getFunction() { result = stmt.getEnclosingFunction() } } @@ -254,7 +254,7 @@ class TranslatedEmptyStmt extends TranslatedStmt { override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -264,7 +264,7 @@ class TranslatedEmptyStmt extends TranslatedStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } @@ -279,19 +279,19 @@ class TranslatedEmptyStmt extends TranslatedStmt { class TranslatedDeclStmt extends TranslatedStmt { override DeclStmt stmt; - override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) } + override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { none() } override Instruction getFirstInstruction() { - result = getDeclarationEntry(0).getFirstInstruction() + result = this.getDeclarationEntry(0).getFirstInstruction() or - not exists(getDeclarationEntry(0)) and result = getParent().getChildSuccessor(this) + not exists(this.getDeclarationEntry(0)) and result = this.getParent().getChildSuccessor(this) } - private int getChildCount() { result = count(getDeclarationEntry(_)) } + private int getChildCount() { result = count(this.getDeclarationEntry(_)) } IRDeclarationEntry getIRDeclarationEntry(int index) { result.hasIndex(index) and @@ -319,10 +319,10 @@ class TranslatedDeclStmt extends TranslatedStmt { override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | - child = getDeclarationEntry(index) and - if index = (getChildCount() - 1) - then result = getParent().getChildSuccessor(this) - else result = getDeclarationEntry(index + 1).getFirstInstruction() + child = this.getDeclarationEntry(index) and + if index = (this.getChildCount() - 1) + then result = this.getParent().getChildSuccessor(this) + else result = this.getDeclarationEntry(index + 1).getFirstInstruction() ) } } @@ -332,19 +332,19 @@ class TranslatedExprStmt extends TranslatedStmt { TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) } - override TranslatedElement getChild(int id) { id = 0 and result = getExpr() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { none() } - override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getExpr() and - result = getParent().getChildSuccessor(this) + child = this.getExpr() and + result = this.getParent().getChildSuccessor(this) } } @@ -363,16 +363,18 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) } final override Instruction getInitializationSuccessor() { - result = getEnclosingFunction().getReturnSuccessorInstruction() + result = this.getEnclosingFunction().getReturnSuccessorInstruction() } - final override Type getTargetType() { result = getEnclosingFunction().getReturnType() } + final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() } final override TranslatedInitialization getInitialization() { result = getTranslatedInitialization(stmt.getExpr().getFullyConverted()) } - final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() } + final override IRVariable getIRVariable() { + result = this.getEnclosingFunction().getReturnVariable() + } } /** @@ -385,10 +387,10 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt { override TranslatedElement getChild(int id) { id = 0 and - result = getExpr() + result = this.getExpr() } - override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -398,13 +400,13 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getEnclosingFunction().getReturnSuccessorInstruction() and + result = this.getEnclosingFunction().getReturnSuccessorInstruction() and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - child = getExpr() and - result = getInstruction(OnlyInstructionTag()) + child = this.getExpr() and + result = this.getInstruction(OnlyInstructionTag()) } private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) } @@ -421,7 +423,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -431,7 +433,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getEnclosingFunction().getReturnSuccessorInstruction() and + result = this.getEnclosingFunction().getReturnSuccessorInstruction() and kind instanceof GotoEdge } @@ -452,7 +454,7 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt { override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and @@ -511,9 +513,9 @@ class TranslatedTryStmt extends TranslatedStmt { override TryOrMicrosoftTryStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getBody() + id = 0 and result = this.getBody() or - result = getHandler(id - 1) + result = this.getHandler(id - 1) or id = stmt.getNumberOfCatchClauses() + 1 and result = this.getFinally() @@ -525,7 +527,7 @@ class TranslatedTryStmt extends TranslatedStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { // All non-finally children go to the successor of the `try` if @@ -546,19 +548,19 @@ class TranslatedTryStmt extends TranslatedStmt { final Instruction getNextHandler(TranslatedHandler handler) { exists(int index | - handler = getHandler(index) and - result = getHandler(index + 1).getFirstInstruction() + handler = this.getHandler(index) and + result = this.getHandler(index + 1).getFirstInstruction() ) or // The last catch clause flows to the exception successor of the parent // of the `try`, because the exception successor of the `try` itself is // the first catch clause. - handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and - result = getParent().getExceptionSuccessorInstruction() + handler = this.getHandler(stmt.getNumberOfCatchClauses() - 1) and + result = this.getParent().getExceptionSuccessorInstruction() } final override Instruction getExceptionSuccessorInstruction() { - result = getHandler(0).getFirstInstruction() + result = this.getHandler(0).getFirstInstruction() } private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) } @@ -571,19 +573,19 @@ class TranslatedTryStmt extends TranslatedStmt { class TranslatedBlock extends TranslatedStmt { override BlockStmt stmt; - override TranslatedElement getChild(int id) { result = getStmt(id) } + override TranslatedElement getChild(int id) { result = this.getStmt(id) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { - isEmpty() and + this.isEmpty() and opcode instanceof Opcode::NoOp and tag = OnlyInstructionTag() and resultType = getVoidType() } override Instruction getFirstInstruction() { - if isEmpty() - then result = getInstruction(OnlyInstructionTag()) - else result = getStmt(0).getFirstInstruction() + if this.isEmpty() + then result = this.getInstruction(OnlyInstructionTag()) + else result = this.getStmt(0).getFirstInstruction() } private predicate isEmpty() { not exists(stmt.getStmt(0)) } @@ -594,16 +596,16 @@ class TranslatedBlock extends TranslatedStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | - child = getStmt(index) and - if index = (getStmtCount() - 1) - then result = getParent().getChildSuccessor(this) - else result = getStmt(index + 1).getFirstInstruction() + child = this.getStmt(index) and + if index = (this.getStmtCount() - 1) + then result = this.getParent().getChildSuccessor(this) + else result = this.getStmt(index + 1).getFirstInstruction() ) } } @@ -614,18 +616,18 @@ class TranslatedBlock extends TranslatedStmt { abstract class TranslatedHandler extends TranslatedStmt { override Handler stmt; - override TranslatedElement getChild(int id) { id = 1 and result = getBlock() } + override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() } - override Instruction getFirstInstruction() { result = getInstruction(CatchTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(CatchTag()) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getBlock() and result = getParent().getChildSuccessor(this) + child = this.getBlock() and result = this.getParent().getChildSuccessor(this) } override Instruction getExceptionSuccessorInstruction() { // A throw from within a `catch` block flows to the handler for the parent of // the `try`. - result = getParent().getParent().getExceptionSuccessorInstruction() + result = this.getParent().getParent().getExceptionSuccessorInstruction() } TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) } @@ -647,23 +649,23 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler { override TranslatedElement getChild(int id) { result = super.getChild(id) or - id = 0 and result = getParameter() + id = 0 and result = this.getParameter() } override Instruction getChildSuccessor(TranslatedElement child) { result = super.getChildSuccessor(child) or - child = getParameter() and result = getBlock().getFirstInstruction() + child = this.getParameter() and result = this.getBlock().getFirstInstruction() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = CatchTag() and ( kind instanceof GotoEdge and - result = getParameter().getFirstInstruction() + result = this.getParameter().getFirstInstruction() or kind instanceof ExceptionEdge and - result = getParent().(TranslatedTryStmt).getNextHandler(this) + result = this.getParent().(TranslatedTryStmt).getNextHandler(this) ) } @@ -692,7 +694,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = CatchTag() and kind instanceof GotoEdge and - result = getBlock().getFirstInstruction() + result = this.getBlock().getFirstInstruction() } } @@ -700,19 +702,19 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { override IfStmt stmt; override Instruction getFirstInstruction() { - if hasInitialization() - then result = getInitialization().getFirstInstruction() - else result = getFirstConditionInstruction() + if this.hasInitialization() + then result = this.getInitialization().getFirstInstruction() + else result = this.getFirstConditionInstruction() } override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() + id = 0 and result = this.getInitialization() or - id = 1 and result = getCondition() + id = 1 and result = this.getCondition() or - id = 2 and result = getThen() + id = 2 and result = this.getThen() or - id = 3 and result = getElse() + id = 3 and result = this.getElse() } private predicate hasInitialization() { exists(stmt.getInitialization()) } @@ -726,7 +728,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { } private Instruction getFirstConditionInstruction() { - result = getCondition().getFirstInstruction() + result = this.getCondition().getFirstInstruction() } private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) } @@ -738,23 +740,23 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and - result = getThen().getFirstInstruction() + child = this.getCondition() and + result = this.getThen().getFirstInstruction() } override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and - if hasElse() - then result = getElse().getFirstInstruction() - else result = getParent().getChildSuccessor(this) + child = this.getCondition() and + if this.hasElse() + then result = this.getElse().getFirstInstruction() + else result = this.getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and - result = getFirstConditionInstruction() + child = this.getInitialization() and + result = this.getFirstConditionInstruction() or - (child = getThen() or child = getElse()) and - result = getParent().getChildSuccessor(this) + (child = this.getThen() or child = this.getElse()) and + result = this.getParent().getChildSuccessor(this) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -772,17 +774,17 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } final Instruction getFirstConditionInstruction() { - if hasCondition() - then result = getCondition().getFirstInstruction() - else result = getBody().getFirstInstruction() + if this.hasCondition() + then result = this.getCondition().getFirstInstruction() + else result = this.getBody().getFirstInstruction() } final predicate hasCondition() { exists(stmt.getCondition()) } override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() + id = 0 and result = this.getCondition() or - id = 1 and result = getBody() + id = 1 and result = this.getBody() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -792,31 +794,31 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } final override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and result = getBody().getFirstInstruction() + child = this.getCondition() and result = this.getBody().getFirstInstruction() } final override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and result = getParent().getChildSuccessor(this) + child = this.getCondition() and result = this.getParent().getChildSuccessor(this) } } class TranslatedWhileStmt extends TranslatedLoop { TranslatedWhileStmt() { stmt instanceof WhileStmt } - override Instruction getFirstInstruction() { result = getFirstConditionInstruction() } + override Instruction getFirstInstruction() { result = this.getFirstConditionInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getBody() and result = getFirstConditionInstruction() + child = this.getBody() and result = this.getFirstConditionInstruction() } } class TranslatedDoStmt extends TranslatedLoop { TranslatedDoStmt() { stmt instanceof DoStmt } - override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() } + override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getBody() and result = getFirstConditionInstruction() + child = this.getBody() and result = this.getFirstConditionInstruction() } } @@ -824,13 +826,13 @@ class TranslatedForStmt extends TranslatedLoop { override ForStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() + id = 0 and result = this.getInitialization() or - id = 1 and result = getCondition() + id = 1 and result = this.getCondition() or - id = 2 and result = getUpdate() + id = 2 and result = this.getUpdate() or - id = 3 and result = getBody() + id = 3 and result = this.getBody() } private TranslatedStmt getInitialization() { @@ -844,23 +846,23 @@ class TranslatedForStmt extends TranslatedLoop { private predicate hasUpdate() { exists(stmt.getUpdate()) } override Instruction getFirstInstruction() { - if hasInitialization() - then result = getInitialization().getFirstInstruction() - else result = getFirstConditionInstruction() + if this.hasInitialization() + then result = this.getInitialization().getFirstInstruction() + else result = this.getFirstConditionInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and - result = getFirstConditionInstruction() + child = this.getInitialization() and + result = this.getFirstConditionInstruction() or ( - child = getBody() and - if hasUpdate() - then result = getUpdate().getFirstInstruction() - else result = getFirstConditionInstruction() + child = this.getBody() and + if this.hasUpdate() + then result = this.getUpdate().getFirstInstruction() + else result = this.getFirstConditionInstruction() ) or - child = getUpdate() and result = getFirstConditionInstruction() + child = this.getUpdate() and result = this.getFirstConditionInstruction() } } @@ -875,39 +877,39 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { override RangeBasedForStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getRangeVariableDeclStmt() + id = 0 and result = this.getRangeVariableDeclStmt() or // Note: `__begin` and `__end` are declared by the same `DeclStmt` - id = 1 and result = getBeginEndVariableDeclStmt() + id = 1 and result = this.getBeginEndVariableDeclStmt() or - id = 2 and result = getCondition() + id = 2 and result = this.getCondition() or - id = 3 and result = getUpdate() + id = 3 and result = this.getUpdate() or - id = 4 and result = getVariableDeclStmt() + id = 4 and result = this.getVariableDeclStmt() or - id = 5 and result = getBody() + id = 5 and result = this.getBody() } override Instruction getFirstInstruction() { - result = getRangeVariableDeclStmt().getFirstInstruction() + result = this.getRangeVariableDeclStmt().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - child = getRangeVariableDeclStmt() and - result = getBeginEndVariableDeclStmt().getFirstInstruction() + child = this.getRangeVariableDeclStmt() and + result = this.getBeginEndVariableDeclStmt().getFirstInstruction() or - child = getBeginEndVariableDeclStmt() and - result = getCondition().getFirstInstruction() + child = this.getBeginEndVariableDeclStmt() and + result = this.getCondition().getFirstInstruction() or - child = getVariableDeclStmt() and - result = getBody().getFirstInstruction() + child = this.getVariableDeclStmt() and + result = this.getBody().getFirstInstruction() or - child = getBody() and - result = getUpdate().getFirstInstruction() + child = this.getBody() and + result = this.getUpdate().getFirstInstruction() or - child = getUpdate() and - result = getCondition().getFirstInstruction() + child = this.getUpdate() and + result = this.getCondition().getFirstInstruction() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -917,11 +919,11 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and result = getVariableDeclStmt().getFirstInstruction() + child = this.getCondition() and result = this.getVariableDeclStmt().getFirstInstruction() } override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and result = getParent().getChildSuccessor(this) + child = this.getCondition() and result = this.getParent().getChildSuccessor(this) } private TranslatedDeclStmt getRangeVariableDeclStmt() { @@ -961,7 +963,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { class TranslatedJumpStmt extends TranslatedStmt { override JumpStmt stmt; - override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } override TranslatedElement getChild(int id) { none() } @@ -996,22 +998,22 @@ class TranslatedSwitchStmt extends TranslatedStmt { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) } - private Instruction getFirstExprInstruction() { result = getExpr().getFirstInstruction() } + private Instruction getFirstExprInstruction() { result = this.getExpr().getFirstInstruction() } private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } override Instruction getFirstInstruction() { - if hasInitialization() - then result = getInitialization().getFirstInstruction() - else result = getFirstExprInstruction() + if this.hasInitialization() + then result = this.getInitialization().getFirstInstruction() + else result = this.getFirstExprInstruction() } override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() + id = 0 and result = this.getInitialization() or - id = 1 and result = getExpr() + id = 1 and result = this.getExpr() or - id = 2 and result = getBody() + id = 2 and result = this.getBody() } private predicate hasInitialization() { exists(stmt.getInitialization()) } @@ -1029,7 +1031,7 @@ class TranslatedSwitchStmt extends TranslatedStmt { override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { tag = SwitchBranchTag() and operandTag instanceof ConditionOperandTag and - result = getExpr().getResult() + result = this.getExpr().getResult() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { @@ -1043,15 +1045,15 @@ class TranslatedSwitchStmt extends TranslatedStmt { not stmt.hasDefaultCase() and tag = SwitchBranchTag() and kind instanceof DefaultEdge and - result = getParent().getChildSuccessor(this) + result = this.getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getFirstExprInstruction() + child = this.getInitialization() and result = this.getFirstExprInstruction() or - child = getExpr() and result = getInstruction(SwitchBranchTag()) + child = this.getExpr() and result = this.getInstruction(SwitchBranchTag()) or - child = getBody() and result = getParent().getChildSuccessor(this) + child = this.getBody() and result = this.getParent().getChildSuccessor(this) } } @@ -1063,9 +1065,9 @@ class TranslatedAsmStmt extends TranslatedStmt { } override Instruction getFirstInstruction() { - if exists(getChild(0)) - then result = getChild(0).getFirstInstruction() - else result = getInstruction(AsmTag()) + if exists(this.getChild(0)) + then result = this.getChild(0).getFirstInstruction() + else result = this.getInstruction(AsmTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -1078,7 +1080,7 @@ class TranslatedAsmStmt extends TranslatedStmt { exists(int index | tag = AsmTag() and operandTag = asmOperand(index) and - result = getChild(index).getResult() + result = this.getChild(index).getResult() ) } @@ -1092,16 +1094,16 @@ class TranslatedAsmStmt extends TranslatedStmt { override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AsmTag() and - result = getParent().getChildSuccessor(this) and + result = this.getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | - child = getChild(index) and - if exists(getChild(index + 1)) - then result = getChild(index + 1).getFirstInstruction() - else result = getInstruction(AsmTag()) + child = this.getChild(index) and + if exists(this.getChild(index + 1)) + then result = this.getChild(index + 1).getFirstInstruction() + else result = this.getInstruction(AsmTag()) ) } } From bfc48efdaa574f355e5d5a97acf50ce7b237285a Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Wed, 3 May 2023 10:48:00 +0200 Subject: [PATCH 95/96] C#: Make implicit this receivers explicit --- csharp/ql/lib/semmle/code/cil/Attribute.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp/ql/lib/semmle/code/cil/Attribute.qll b/csharp/ql/lib/semmle/code/cil/Attribute.qll index 0f98c1c5ed4..1ec53603463 100644 --- a/csharp/ql/lib/semmle/code/cil/Attribute.qll +++ b/csharp/ql/lib/semmle/code/cil/Attribute.qll @@ -12,9 +12,9 @@ class Attribute extends Element, @cil_attribute { Method getConstructor() { cil_attribute(this, _, result) } /** Gets the type of this attribute. */ - Type getType() { result = getConstructor().getDeclaringType() } + Type getType() { result = this.getConstructor().getDeclaringType() } - override string toString() { result = "[" + getType().getName() + "(...)]" } + override string toString() { result = "[" + this.getType().getName() + "(...)]" } /** Gets the value of the `i`th argument of this attribute. */ string getArgument(int i) { cil_attribute_positional_argument(this, i, result) } @@ -23,9 +23,9 @@ class Attribute extends Element, @cil_attribute { string getNamedArgument(string name) { cil_attribute_named_argument(this, name, result) } /** Gets an argument of this attribute, if any. */ - string getAnArgument() { result = getArgument(_) or result = getNamedArgument(_) } + string getAnArgument() { result = this.getArgument(_) or result = this.getNamedArgument(_) } - override CS::Location getLocation() { result = getDeclaration().getLocation() } + override CS::Location getLocation() { result = this.getDeclaration().getLocation() } } /** A generic attribute to a declaration. */ From efdaffedee1bb05555f109216e424780d7e1b50e Mon Sep 17 00:00:00 2001 From: Kasper Svendsen Date: Wed, 3 May 2023 10:49:46 +0200 Subject: [PATCH 96/96] JS: Make implicit this receivers explicit --- .../lib/semmle/javascript/ES2015Modules.qll | 104 +++++++++--------- .../javascript/dataflow/Configuration.qll | 14 +-- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index 6f139fb95b0..1f84ddc0f1f 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -20,20 +20,20 @@ class ES2015Module extends Module { override ModuleScope getScope() { result.getScopeElement() = this } /** Gets the full path of the file containing this module. */ - override string getPath() { result = getFile().getAbsolutePath() } + override string getPath() { result = this.getFile().getAbsolutePath() } /** Gets the short name of this module without file extension. */ - override string getName() { result = getFile().getStem() } + override string getName() { result = this.getFile().getStem() } /** Gets an export declaration in this module. */ ExportDeclaration getAnExport() { result.getTopLevel() = this } override DataFlow::Node getAnExportedValue(string name) { - exists(ExportDeclaration ed | ed = getAnExport() and result = ed.getSourceNode(name)) + exists(ExportDeclaration ed | ed = this.getAnExport() and result = ed.getSourceNode(name)) } /** Holds if this module exports variable `v` under the name `name`. */ - predicate exportsAs(LexicalName v, string name) { getAnExport().exportsAs(v, name) } + predicate exportsAs(LexicalName v, string name) { this.getAnExport().exportsAs(v, name) } override predicate isStrict() { // modules are implicitly strict @@ -86,9 +86,9 @@ private predicate hasBothNamedAndDefaultExports(ES2015Module mod) { * ``` */ class ImportDeclaration extends Stmt, Import, @import_declaration { - override ES2015Module getEnclosingModule() { result = getTopLevel() } + override ES2015Module getEnclosingModule() { result = this.getTopLevel() } - override PathExpr getImportedPath() { result = getChildExpr(-1) } + override PathExpr getImportedPath() { result = this.getChildExpr(-1) } /** * Gets the object literal passed as part of the `assert` clause in this import declaration. @@ -101,24 +101,24 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { ObjectExpr getImportAssertion() { result = this.getChildExpr(-10) } /** Gets the `i`th import specifier of this import declaration. */ - ImportSpecifier getSpecifier(int i) { result = getChildExpr(i) } + ImportSpecifier getSpecifier(int i) { result = this.getChildExpr(i) } /** Gets an import specifier of this import declaration. */ - ImportSpecifier getASpecifier() { result = getSpecifier(_) } + ImportSpecifier getASpecifier() { result = this.getSpecifier(_) } override DataFlow::Node getImportedModuleNode() { // `import * as http from 'http'` or `import http from `http`' exists(ImportSpecifier is | - is = getASpecifier() and + is = this.getASpecifier() and result = DataFlow::valueNode(is) | is instanceof ImportNamespaceSpecifier and - count(getASpecifier()) = 1 + count(this.getASpecifier()) = 1 or // For compatibility with the non-standard implementation of default imports, // treat default imports as namespace imports in cases where it can't cause ambiguity // between named exports and the properties of a default-exported object. - not hasBothNamedAndDefaultExports(getImportedModule()) and + not hasBothNamedAndDefaultExports(this.getImportedModule()) and is.getImportedName() = "default" ) or @@ -136,7 +136,7 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { private class LiteralImportPath extends PathExpr, ConstantString { LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) } - override string getValue() { result = getStringValue() } + override string getValue() { result = this.getStringValue() } } /** @@ -159,7 +159,7 @@ private class LiteralImportPath extends PathExpr, ConstantString { */ class ImportSpecifier extends Expr, @import_specifier { /** Gets the imported symbol; undefined for default and namespace import specifiers. */ - Identifier getImported() { result = getChildExpr(0) } + Identifier getImported() { result = this.getChildExpr(0) } /** * Gets the name of the imported symbol. @@ -176,10 +176,10 @@ class ImportSpecifier extends Expr, @import_specifier { * The names of the imported symbols for the first three of them are, respectively, * `x`, `y` and `default`, while the last one does not import an individual symbol. */ - string getImportedName() { result = getImported().getName() } + string getImportedName() { result = this.getImported().getName() } /** Gets the local variable into which this specifier imports. */ - VarDecl getLocal() { result = getChildExpr(1) } + VarDecl getLocal() { result = this.getChildExpr(1) } override string getAPrimaryQlClass() { result = "ImportSpecifier" } @@ -240,10 +240,10 @@ class ImportNamespaceSpecifier extends ImportSpecifier, @import_namespace_specif * ``` */ class BulkImportDeclaration extends ImportDeclaration { - BulkImportDeclaration() { getASpecifier() instanceof ImportNamespaceSpecifier } + BulkImportDeclaration() { this.getASpecifier() instanceof ImportNamespaceSpecifier } /** Gets the local namespace variable under which the module is imported. */ - VarDecl getLocal() { result = getASpecifier().getLocal() } + VarDecl getLocal() { result = this.getASpecifier().getLocal() } } /** @@ -260,12 +260,12 @@ class SelectiveImportDeclaration extends ImportDeclaration { /** Holds if `local` is the local variable into which `imported` is imported. */ predicate importsAs(string imported, LexicalDecl local) { - exists(ImportSpecifier spec | spec = getASpecifier() | + exists(ImportSpecifier spec | spec = this.getASpecifier() | imported = spec.getImported().getName() and local = spec.getLocal() ) or - imported = "default" and local = getASpecifier().(ImportDefaultSpecifier).getLocal() + imported = "default" and local = this.getASpecifier().(ImportDefaultSpecifier).getLocal() } } @@ -347,15 +347,15 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { */ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declaration { /** Gets the name of the module from which this declaration re-exports. */ - override ConstantString getImportedPath() { result = getChildExpr(0) } + override ConstantString getImportedPath() { result = this.getChildExpr(0) } override predicate exportsAs(LexicalName v, string name) { - getReExportedES2015Module().exportsAs(v, name) and + this.getReExportedES2015Module().exportsAs(v, name) and not isShadowedFromBulkExport(this, name) } override DataFlow::Node getSourceNode(string name) { - result = getReExportedES2015Module().getAnExport().getSourceNode(name) + result = this.getReExportedES2015Module().getAnExport().getSourceNode(name) } } @@ -392,22 +392,22 @@ private predicate isShadowedFromBulkExport(BulkReExportDeclaration reExport, str */ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declaration { /** Gets the operand statement or expression that is exported by this declaration. */ - ExprOrStmt getOperand() { result = getChild(0) } + ExprOrStmt getOperand() { result = this.getChild(0) } override predicate exportsAs(LexicalName v, string name) { - name = "default" and v = getADecl().getVariable() + name = "default" and v = this.getADecl().getVariable() } /** Gets the declaration, if any, exported by this default export. */ VarDecl getADecl() { - exists(ExprOrStmt op | op = getOperand() | + exists(ExprOrStmt op | op = this.getOperand() | result = op.(FunctionDeclStmt).getIdentifier() or result = op.(ClassDeclStmt).getIdentifier() ) } override DataFlow::Node getSourceNode(string name) { - name = "default" and result = DataFlow::valueNode(getOperand()) + name = "default" and result = DataFlow::valueNode(this.getOperand()) } } @@ -424,7 +424,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar */ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaration { /** Gets the operand statement or expression that is exported by this declaration. */ - ExprOrStmt getOperand() { result = getChild(-1) } + ExprOrStmt getOperand() { result = this.getChild(-1) } /** * Gets an identifier, if any, exported as part of a declaration by this named export. @@ -433,7 +433,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio * That is, it includes the `v` in `export var v` but not in `export {v}`. */ Identifier getAnExportedDecl() { - exists(ExprOrStmt op | op = getOperand() | + exists(ExprOrStmt op | op = this.getOperand() | result = op.(DeclStmt).getADecl().getBindingPattern().getABindingVarRef() or result = op.(FunctionDeclStmt).getIdentifier() or result = op.(ClassDeclStmt).getIdentifier() or @@ -446,14 +446,14 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio } /** Gets the variable declaration, if any, exported by this named export. */ - VarDecl getADecl() { result = getAnExportedDecl() } + VarDecl getADecl() { result = this.getAnExportedDecl() } override predicate exportsAs(LexicalName v, string name) { - exists(LexicalDecl vd | vd = getAnExportedDecl() | + exists(LexicalDecl vd | vd = this.getAnExportedDecl() | name = vd.getName() and v = vd.getALexicalName() ) or - exists(ExportSpecifier spec | spec = getASpecifier() and name = spec.getExportedName() | + exists(ExportSpecifier spec | spec = this.getASpecifier() and name = spec.getExportedName() | v = spec.getLocal().(LexicalAccess).getALexicalName() or this.(ReExportDeclaration).getReExportedES2015Module().exportsAs(v, spec.getLocalName()) @@ -461,20 +461,20 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio } override DataFlow::Node getSourceNode(string name) { - exists(VarDef d | d.getTarget() = getADecl() | + exists(VarDef d | d.getTarget() = this.getADecl() | name = d.getTarget().(VarDecl).getName() and result = DataFlow::valueNode(d.getSource()) ) or - exists(ObjectPattern obj | obj = getOperand().(DeclStmt).getADecl().getBindingPattern() | + exists(ObjectPattern obj | obj = this.getOperand().(DeclStmt).getADecl().getBindingPattern() | exists(DataFlow::PropRead read | read = result | read.getBase() = obj.flow() and name = read.getPropertyName() ) ) or - exists(ExportSpecifier spec | spec = getASpecifier() and name = spec.getExportedName() | - not exists(getImportedPath()) and result = DataFlow::valueNode(spec.getLocal()) + exists(ExportSpecifier spec | spec = this.getASpecifier() and name = spec.getExportedName() | + not exists(this.getImportedPath()) and result = DataFlow::valueNode(spec.getLocal()) or exists(ReExportDeclaration red | red = this | result = red.getReExportedES2015Module().getAnExport().getSourceNode(spec.getLocalName()) @@ -483,20 +483,20 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio } /** Gets the module from which the exports are taken if this is a re-export. */ - ConstantString getImportedPath() { result = getChildExpr(-2) } + ConstantString getImportedPath() { result = this.getChildExpr(-2) } /** Gets the `i`th export specifier of this declaration. */ - ExportSpecifier getSpecifier(int i) { result = getChildExpr(i) } + ExportSpecifier getSpecifier(int i) { result = this.getChildExpr(i) } /** Gets an export specifier of this declaration. */ - ExportSpecifier getASpecifier() { result = getSpecifier(_) } + ExportSpecifier getASpecifier() { result = this.getSpecifier(_) } } /** * An export declaration with the `type` modifier. */ private class TypeOnlyExportDeclaration extends ExportNamedDeclaration { - TypeOnlyExportDeclaration() { isTypeOnly() } + TypeOnlyExportDeclaration() { this.isTypeOnly() } override predicate exportsAs(LexicalName v, string name) { super.exportsAs(v, name) and @@ -530,13 +530,13 @@ private class TypeOnlyExportDeclaration extends ExportNamedDeclaration { */ class ExportSpecifier extends Expr, @exportspecifier { /** Gets the declaration to which this specifier belongs. */ - ExportDeclaration getExportDeclaration() { result = getParent() } + ExportDeclaration getExportDeclaration() { result = this.getParent() } /** Gets the local symbol that is being exported. */ - Identifier getLocal() { result = getChildExpr(0) } + Identifier getLocal() { result = this.getChildExpr(0) } /** Gets the name under which the symbol is exported. */ - Identifier getExported() { result = getChildExpr(1) } + Identifier getExported() { result = this.getChildExpr(1) } /** * Gets the local name of the exported symbol, that is, the name @@ -562,7 +562,7 @@ class ExportSpecifier extends Expr, @exportspecifier { * The sixth one (unlike the fourth one) _does_ have a local name * (that is, `default`), since it is a re-export. */ - string getLocalName() { result = getLocal().getName() } + string getLocalName() { result = this.getLocal().getName() } /** * Gets the name under which the symbol is exported. @@ -581,7 +581,7 @@ class ExportSpecifier extends Expr, @exportspecifier { * `x`, `z`, `f` and `default`, while the last one does not have * an exported name since it does not export a unique symbol. */ - string getExportedName() { result = getExported().getName() } + string getExportedName() { result = this.getExported().getName() } override string getAPrimaryQlClass() { result = "ExportSpecifier" } } @@ -630,11 +630,11 @@ class ExportDefaultSpecifier extends ExportSpecifier, @export_default_specifier * ``` */ class ReExportDefaultSpecifier extends ExportDefaultSpecifier { - ReExportDefaultSpecifier() { getExportDeclaration() instanceof ReExportDeclaration } + ReExportDefaultSpecifier() { this.getExportDeclaration() instanceof ReExportDeclaration } override string getLocalName() { result = "default" } - override string getExportedName() { result = getExported().getName() } + override string getExportedName() { result = this.getExported().getName() } } /** @@ -671,15 +671,15 @@ abstract class ReExportDeclaration extends ExportDeclaration { abstract ConstantString getImportedPath(); /** Gets the module from which this declaration re-exports, if it is an ES2015 module. */ - ES2015Module getReExportedES2015Module() { result = getReExportedModule() } + ES2015Module getReExportedES2015Module() { result = this.getReExportedModule() } /** Gets the module from which this declaration re-exports. */ cached Module getReExportedModule() { Stages::Imports::ref() and - result.getFile() = getEnclosingModule().resolve(getImportedPath()) + result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath()) or - result = resolveFromTypeRoot() + result = this.resolveFromTypeRoot() } /** @@ -689,9 +689,9 @@ abstract class ReExportDeclaration extends ExportDeclaration { result.getFile() = min(TypeRootFolder typeRoot | | - typeRoot.getModuleFile(getImportedPath().getStringValue()) + typeRoot.getModuleFile(this.getImportedPath().getStringValue()) order by - typeRoot.getSearchPriority(getFile().getParentContainer()) + typeRoot.getSearchPriority(this.getFile().getParentContainer()) ) } } @@ -700,7 +700,7 @@ abstract class ReExportDeclaration extends ExportDeclaration { private class LiteralReExportPath extends PathExpr, ConstantString { LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) } - override string getValue() { result = getStringValue() } + override string getValue() { result = this.getStringValue() } } /** diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll index 9b90da92a05..29c50fca302 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll @@ -143,7 +143,7 @@ abstract class Configuration extends string { * indicating whether the step preserves values or just taintedness. */ predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg, boolean valuePreserving) { - isAdditionalFlowStep(src, trg) and valuePreserving = true + this.isAdditionalFlowStep(src, trg) and valuePreserving = true } /** @@ -205,7 +205,7 @@ abstract class Configuration extends string { isSource(_, this, _) and isSink(_, this, _) and exists(SourcePathNode flowsource, SinkPathNode flowsink | - hasFlowPath(flowsource, flowsink) and + this.hasFlowPath(flowsource, flowsink) and source = flowsource.getNode() and sink = flowsink.getNode() ) @@ -297,7 +297,7 @@ abstract class FlowLabel extends string { * Holds if this is one of the standard flow labels `FlowLabel::data()` * or `FlowLabel::taint()`. */ - final predicate isDataOrTaint() { isData() or isTaint() } + final predicate isDataOrTaint() { this.isData() or this.isTaint() } } /** @@ -1726,7 +1726,7 @@ class PathNode extends TPathNode { /** * Gets a flow label for the path node. */ - FlowLabel getFlowLabel() { result = getPathSummary().getEndLabel() } + FlowLabel getFlowLabel() { result = this.getPathSummary().getEndLabel() } } /** Gets the mid node corresponding to `src`. */ @@ -1957,15 +1957,15 @@ private class BarrierGuardFunction extends Function { | exists(SsaExplicitDefinition ssa | ssa.getDef().getSource() = returnExpr and - ssa.getVariable().getAUse() = getAReturnedExpr() + ssa.getVariable().getAUse() = this.getAReturnedExpr() ) or - returnExpr = getAReturnedExpr() + returnExpr = this.getAReturnedExpr() ) and sanitizedParameter.flowsToExpr(e) and barrierGuardBlocksExpr(guard, guardOutcome, e, label) ) and - sanitizedParameter.getParameter() = getParameter(paramIndex) + sanitizedParameter.getParameter() = this.getParameter(paramIndex) } /**